diff --git a/.air.toml b/.air.toml
index 78321b7a6a3..87083f809aa 100644
--- a/.air.toml
+++ b/.air.toml
@@ -7,7 +7,6 @@ exclude_unchanged = true
follow_symlink = true
include_dir = ["apps", "conf", "devenv/dev-dashboards", "pkg", "public/views"]
include_ext = ["go", "ini", "toml", "html", "json"]
-pre_cmd = ["make gen-go"]
stop_on_error = true
send_interrupt = true
kill_delay = 500
diff --git a/.betterer.eslint.config.js b/.betterer.eslint.config.js
index 8d742ae5187..3b44630965e 100644
--- a/.betterer.eslint.config.js
+++ b/.betterer.eslint.config.js
@@ -35,7 +35,7 @@ module.exports = [
'data/',
'deployment_tools_config.json',
'devenv',
- 'e2e/test-plugins',
+ 'e2e-playwright/test-plugins',
'e2e/tmp',
'packages/grafana-ui/src/components/Icon/iconBundle.ts',
'pkg',
@@ -104,6 +104,7 @@ module.exports = [
'**/__mocks__/**',
'**/public/test/**',
'**/mocks.{ts,tsx}',
+ '**/mocks/**/*.{ts,tsx}',
'**/spec/**/*.{ts,tsx}',
],
rules: {
diff --git a/.betterer.results b/.betterer.results
index bfa5bfe7558..8c04156fcf0 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -476,8 +476,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"packages/grafana-prometheus/src/querybuilder/shared/types.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-prometheus/src/resource_clients.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@@ -489,9 +488,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"]
],
- "packages/grafana-prometheus/src/test/mocks/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"packages/grafana-prometheus/src/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -961,9 +957,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`profiler\`)", "6"],
[0, 0, 0, "Do not re-export imported variable (\`updateLegendValues\`)", "7"]
],
- "public/app/core/navigation/mocks/routeProps.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/core/navigation/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -1499,22 +1492,9 @@ exports[`better eslint`] = {
"public/app/features/browse-dashboards/components/NewFolderForm.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"]
],
- "public/app/features/browse-dashboards/state/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"]
- ],
"public/app/features/connections/components/ConnectionsRedirectNotice/index.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
],
- "public/app/features/connections/pages/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./AddNewConnectionPage\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./DataSourceDashboardsPage\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./DataSourceDetailsPage\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./DataSourcesListPage\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./EditDataSourcePage\`)", "4"],
- [0, 0, 0, "Do not re-export imported variable (\`./NewDataSourcePage\`)", "5"]
- ],
"public/app/features/connections/tabs/ConnectData/CardGrid/CardGrid.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Card components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"]
],
@@ -1568,13 +1548,6 @@ exports[`better eslint`] = {
"public/app/features/correlations/components/EmptyCorrelationsCTA.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Card components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"]
],
- "public/app/features/correlations/components/Wizard/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"]
- ],
- "public/app/features/correlations/mocks/useCorrelations.mocks.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/features/correlations/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -1713,15 +1686,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/serialization/transformToV1TypesUtils.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx:5381": [
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "2"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "3"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "4"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"],
- [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"]
- ],
"public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsEdit.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -1730,10 +1694,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "4"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"]
],
- "public/app/features/dashboard-scene/settings/annotations/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsEdit\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsList\`)", "1"]
- ],
"public/app/features/dashboard-scene/settings/links/DashboardLinkForm.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -1781,13 +1741,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/features/dashboard-scene/settings/version-history/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./HistorySrv\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryButtons\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryComparison\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryHeader\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./VersionHistoryTable\`)", "4"]
- ],
"public/app/features/dashboard-scene/sharing/ShareButton/share-externally/EmailShare/ConfigEmailSharing/ConfigEmailSharing.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"]
],
@@ -1870,10 +1823,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"]
],
- "public/app/features/dashboard/components/AnnotationSettings/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsEdit\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./AnnotationSettingsList\`)", "1"]
- ],
"public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -1956,10 +1905,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard/components/Inspector/PanelInspector.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/dashboard/components/LinksSettings/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./LinkSettingsEdit\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./LinkSettingsList\`)", "1"]
- ],
"public/app/features/dashboard/components/PanelEditor/DynamicConfigValueEditor.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"]
@@ -2228,10 +2173,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
- "public/app/features/dataframe-import/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"]
- ],
"public/app/features/datasources/components/DataSourceTypeCard.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Card components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
@@ -2251,14 +2192,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/features/datasources/state/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"]
- ],
"public/app/features/datasources/state/navModel.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -2299,24 +2232,6 @@ exports[`better eslint`] = {
"public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx:5381": [
[0, 0, 0, "\'VerticalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
],
- "public/app/features/dimensions/editors/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"]
- ],
- "public/app/features/dimensions/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "6"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "7"]
- ],
"public/app/features/dimensions/scale.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -2362,17 +2277,6 @@ exports[`better eslint`] = {
"public/app/features/explore/TraceView/components/demo/trace-generators.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/explore/TraceView/components/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./TracePageHeader\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./TraceTimelineViewer/SpanDetail/DetailState\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./TraceTimelineViewer\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./model/transform-trace-data\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./settings/SpanBarSettings\`)", "4"],
- [0, 0, 0, "Do not re-export imported variable (\`./utils/filter-spans\`)", "5"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "6"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "7"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "8"]
- ],
"public/app/features/explore/TraceView/components/model/ddg/types.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./PathElem\`)", "0"]
],
@@ -2393,21 +2297,9 @@ exports[`better eslint`] = {
"public/app/features/explore/TraceView/components/model/transform-trace-data.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/explore/TraceView/components/types/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`../settings/SpanBarSettings\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./TNil\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./TTraceTimeline\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./links\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./trace\`)", "4"]
- ],
"public/app/features/explore/TraceView/components/utils/DraggableManager/demo/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./DraggableManagerDemo\`)", "0"]
],
- "public/app/features/explore/TraceView/components/utils/DraggableManager/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./DraggableManager\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./EUpdateTypes\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"]
- ],
"public/app/features/explore/TraceView/createSpanLink.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
@@ -2444,8 +2336,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/geo/utils/frameVectorSource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/inspector/InspectDataOptions.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
@@ -2602,36 +2493,15 @@ exports[`better eslint`] = {
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "2"]
],
- "public/app/features/plugins/admin/components/Badges/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./PluginDeprecatedBadge\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./PluginDisabledBadge\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./PluginEnterpriseBadge\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./PluginInstallBadge\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./PluginUpdateAvailableBadge\`)", "4"]
- ],
"public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./GetStartedWithPlugin\`)", "0"]
],
- "public/app/features/plugins/admin/components/InstallControls/index.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./InstallControlsButton\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./InstallControlsWarning\`)", "1"]
- ],
"public/app/features/plugins/admin/components/PluginDetailsPage.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/plugins/admin/mocks/catalogPlugin.mock.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
- "public/app/features/plugins/admin/mocks/localPlugin.mock.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/features/plugins/admin/mocks/remotePlugin.mock.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/features/plugins/admin/pages/Browse.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -2666,10 +2536,10 @@ exports[`better eslint`] = {
"public/app/features/plugins/loader/sharedDependencies.ts:5381": [
[0, 0, 0, "* import is invalid because \'Layout,HorizontalGroup,VerticalGroup\' from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
],
- "public/app/features/plugins/sandbox/distortion_map.ts:5381": [
+ "public/app/features/plugins/sandbox/distortions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/plugins/sandbox/sandbox_plugin_loader.ts:5381": [
+ "public/app/features/plugins/sandbox/sandboxPluginLoader.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
@@ -2913,10 +2783,6 @@ exports[`better eslint`] = {
"public/app/features/transformers/editors/CalculateFieldTransformerEditor/WindowOptionsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/transformers/editors/CalculateFieldTransformerEditor/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`CalculateFieldTransformerEditor\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`calculateFieldTransformRegistryItem\`)", "1"]
- ],
"public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -2982,12 +2848,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"]
],
- "public/app/features/users/mocks/userMocks.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"],
- [0, 0, 0, "Do not use any type assertions.", "3"]
- ],
"public/app/features/variables/adapters.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3022,10 +2882,7 @@ exports[`better eslint`] = {
],
"public/app/features/variables/inspect/NetworkGraph.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "4"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/variables/inspect/VariablesUnknownTable.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
@@ -3142,10 +2999,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/plugins/datasource/azuremonitor/azureMetadata/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"]
- ],
"public/app/plugins/datasource/azuremonitor/components/ArgQueryEditor/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./ArgQueryEditor\`)", "0"]
],
@@ -3212,26 +3065,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"]
],
- "public/app/plugins/datasource/azuremonitor/mocks/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/azuremonitor/mocks/panelData.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"]
- ],
- "public/app/plugins/datasource/azuremonitor/mocks/utils.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
- "public/app/plugins/datasource/azuremonitor/mocks/variables.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/azuremonitor/types/index.ts:5381": [
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"]
- ],
"public/app/plugins/datasource/azuremonitor/types/query.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "1"],
@@ -3263,23 +3096,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/plugins/datasource/cloud-monitoring/components/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./Aggregation\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./AliasBy\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./AlignmentFunction\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./Alignment\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./AnnotationsHelp\`)", "4"],
- [0, 0, 0, "Do not re-export imported variable (\`./Fields\`)", "5"],
- [0, 0, 0, "Do not re-export imported variable (\`./GroupBy\`)", "6"],
- [0, 0, 0, "Do not re-export imported variable (\`./LabelFilter\`)", "7"],
- [0, 0, 0, "Do not re-export imported variable (\`./MQLQueryEditor\`)", "8"],
- [0, 0, 0, "Do not re-export imported variable (\`./MetricQueryEditor\`)", "9"],
- [0, 0, 0, "Do not re-export imported variable (\`./PeriodSelect\`)", "10"],
- [0, 0, 0, "Do not re-export imported variable (\`./Preprocessor\`)", "11"],
- [0, 0, 0, "Do not re-export imported variable (\`./Project\`)", "12"],
- [0, 0, 0, "Do not re-export imported variable (\`./SLOQueryEditor\`)", "13"],
- [0, 0, 0, "Do not re-export imported variable (\`./VisualMetricQueryEditor\`)", "14"]
- ],
"public/app/plugins/datasource/cloud-monitoring/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
@@ -3291,14 +3107,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
- "public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringDatasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"]
- ],
- "public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringInstanceSettings.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/plugins/datasource/cloud-monitoring/types/query.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "1"],
@@ -3307,9 +3115,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/cloud-monitoring/types/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "public/app/plugins/datasource/cloud-monitoring/webpack.config.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
- ],
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor/ConfigEditor.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -3347,153 +3152,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
- "public/app/plugins/datasource/cloudwatch/mocks/CloudWatchVariables.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/commentOnlyQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/multiLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/multiLineFullQueryWithCaseClause.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/partialQueryWithFunction.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/partialQueryWithSubquery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/singleLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/whitespaceQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/commentOnlyQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/filterQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./commentOnlyQuery\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./empty\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./filterQuery\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./multiLineFullQuery\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./newCommandQuery\`)", "4"],
- [0, 0, 0, "Do not re-export imported variable (\`./singleLineFullQuery\`)", "5"],
- [0, 0, 0, "Do not re-export imported variable (\`./sortQuery\`)", "6"],
- [0, 0, 0, "Do not re-export imported variable (\`./whitespaceQuery\`)", "7"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/multiLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/newCommandQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/singleLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/sortQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/whitespaceQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/multilineQueries.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/newCommandQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/singleLineQueries.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"],
- [0, 0, 0, "Do not use any type assertions.", "3"],
- [0, 0, 0, "Do not use any type assertions.", "4"],
- [0, 0, 0, "Do not use any type assertions.", "5"],
- [0, 0, 0, "Do not use any type assertions.", "6"],
- [0, 0, 0, "Do not use any type assertions.", "7"],
- [0, 0, 0, "Do not use any type assertions.", "8"],
- [0, 0, 0, "Do not use any type assertions.", "9"],
- [0, 0, 0, "Do not use any type assertions.", "10"],
- [0, 0, 0, "Do not use any type assertions.", "11"],
- [0, 0, 0, "Do not use any type assertions.", "12"],
- [0, 0, 0, "Do not use any type assertions.", "13"],
- [0, 0, 0, "Do not use any type assertions.", "14"],
- [0, 0, 0, "Do not use any type assertions.", "15"],
- [0, 0, 0, "Do not use any type assertions.", "16"],
- [0, 0, 0, "Do not use any type assertions.", "17"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./multiLineFullQuery\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./multiLineIncompleteQueryWithoutNamespace\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./singleLineEmptyQuery\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./singleLineFullQuery\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./singleLineTwoQueries\`)", "4"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/multiLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/multiLineIncompleteQueryWithoutNamespace.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineEmptyQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineFullQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineTwoQueries.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/dashboardOnLoadedEvent.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/dynamic-label-test-data/afterLabelValue.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/dynamic-label-test-data/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./afterLabelValue\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./insideLabelValue\`)", "1"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/dynamic-label-test-data/insideLabelValue.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/afterFunctionQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./afterFunctionQuery\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./secondArgAfterSearchQuery\`)", "1"],
- [0, 0, 0, "Do not re-export imported variable (\`./secondArgQuery\`)", "2"],
- [0, 0, 0, "Do not re-export imported variable (\`./singleLineEmptyQuery\`)", "3"],
- [0, 0, 0, "Do not re-export imported variable (\`./thirdArgAfterSearchQuery\`)", "4"],
- [0, 0, 0, "Do not re-export imported variable (\`./withinStringQuery\`)", "5"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/secondArgAfterSearchQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/secondArgQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/singleLineEmptyQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/thirdArgAfterSearchQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/withinStringQuery.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "public/app/plugins/datasource/cloudwatch/mocks/monarch/Monaco.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
"public/app/plugins/datasource/cloudwatch/types.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3566,9 +3224,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/state/reducer.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/plugins/datasource/elasticsearch/configuration/mocks/configOptions.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/plugins/datasource/elasticsearch/datasource.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3582,11 +3237,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/elasticsearch/test-helpers/render.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/plugins/datasource/elasticsearch/types.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./dataquery.gen\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`ElasticsearchQuery\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"]
- ],
"public/app/plugins/datasource/grafana-postgresql-datasource/configuration/ConfigurationEditor.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -3627,17 +3277,10 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/grafana-testdata-datasource/components/SimulationSchemaForm.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "public/app/plugins/datasource/grafana-testdata-datasource/components/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./RandomWalkEditor\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./StreamingClientEditor\`)", "1"]
- ],
"public/app/plugins/datasource/grafana-testdata-datasource/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
- ],
"public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -3787,10 +3430,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
- "public/app/plugins/datasource/influxdb/mocks/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
"public/app/plugins/datasource/influxdb/query_part.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3817,8 +3456,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`./trace\`)", "0"]
],
"public/app/plugins/datasource/jaeger/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/loki/LanguageProvider.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -3858,13 +3496,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/plugins/datasource/loki/mocks/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
- "public/app/plugins/datasource/loki/mocks/metadataRequest.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -4000,9 +3631,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
- "public/app/plugins/datasource/tempo/webpack.config.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
- ],
"public/app/plugins/datasource/zipkin/QueryField.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -4013,9 +3641,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/zipkin/utils/transforms.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "public/app/plugins/datasource/zipkin/webpack.config.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
- ],
"public/app/plugins/panel/annolist/AnnoListPanel.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -4134,9 +3759,6 @@ exports[`better eslint`] = {
"public/app/plugins/panel/geomap/types.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./panelcfg.gen\`)", "0"]
],
- "public/app/plugins/panel/geomap/utils/layers.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
- ],
"public/app/plugins/panel/geomap/utils/tooltip.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
@@ -4359,9 +3981,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "public/app/types/acl.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`OrgRole\`)", "0"]
- ],
"public/app/types/alerting.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -4383,29 +4002,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
- "public/app/types/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`CoreEvents\`)", "0"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "6"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "7"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "8"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "9"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "10"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "11"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "12"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "13"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "14"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "15"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "16"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "17"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "18"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "19"],
- [0, 0, 0, "Do not use export all (\`export * from ...\`)", "20"]
- ],
"public/app/types/jquery/jquery.d.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -4475,6 +4071,15 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/CallToActionCard/CallToActionCard.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4490,12 +4095,27 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/Dropdown/ButtonSelect.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/FormField/FormField.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/InfoTooltip/InfoTooltip.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/List/List.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/QueryField/QueryField.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/SecretFormField/SecretFormField.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/SecretTextArea/SecretTextArea.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4508,6 +4128,9 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/Select/SelectPerf.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/Slider/RangeSlider.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4517,9 +4140,21 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/ThemeDemos/BorderRadius.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/components/ThemeDemos/EmotionPerfTest.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/ThemeDemos/ThemeDemo.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
+ "packages/grafana-ui/src/components/ThemeDemos/Typography.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
"packages/grafana-ui/src/components/UnitPicker/UnitPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4531,6 +4166,9 @@ exports[`no undocumented stories`] = {
],
"packages/grafana-ui/src/components/VizTooltip/SeriesTable.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
+ ],
+ "packages/grafana-ui/src/utils/useDelayedSwitch.story.tsx:5381": [
+ [0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
]
}`
};
diff --git a/.drone.yml b/.drone.yml
index 9778f442148..bf621c24a1e 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -289,7 +289,7 @@ steps:
- commands:
- npx wait-on@7.0.1 http://$HOST:$PORT
- yarn playwright install --with-deps chromium
- - yarn e2e:playwright
+ - yarn e2e:playwright --grep @plugins
depends_on:
- grafana-server
- build-test-plugins
@@ -761,7 +761,7 @@ steps:
- commands:
- npx wait-on@7.0.1 http://$HOST:$PORT
- yarn playwright install --with-deps chromium
- - yarn e2e:playwright
+ - yarn e2e:playwright --grep @plugins
depends_on:
- grafana-server
- build-test-plugins
@@ -2986,6 +2986,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
-hmac: 1198b1489e48a9ced211633a0325d112814553246847fc7320fb5ac2bcb32b7d
+hmac: d20f1d6e2e8347701f82114ad352f53db57dc95b5b3831941fa93d063a92b9d8
...
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 3e78adb40cb..b37938d86fd 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -80,6 +80,7 @@
/apps/dashboard/ @grafana/grafana-app-platform-squad @grafana/dashboards-squad
/apps/folder/ @grafana/grafana-app-platform-squad
/apps/playlist/ @grafana/grafana-app-platform-squad
+/apps/secret/ @grafana/grafana-operator-experience-squad
/apps/investigations/ @fcjack @matryer @svennergr
/apps/advisor/ @grafana/plugins-platform-backend
/apps/iam/ @grafana/access-squad
@@ -87,7 +88,6 @@
/pkg/apis/ @grafana/grafana-app-platform-squad
/pkg/apis/query @grafana/grafana-datasources-core-services
/pkg/apis/userstorage @grafana/grafana-app-platform-squad @grafana/plugins-platform-backend
-/pkg/apis/secret @grafana/grafana-operator-experience-squad
/pkg/bus/ @grafana/grafana-search-and-storage
/pkg/cmd/ @grafana/grafana-backend-group
/pkg/cmd/grafana-cli/commands/install_command.go @grafana/plugins-platform-backend
@@ -400,8 +400,10 @@
/public/app/core/internationalization/ @grafana/grafana-frontend-platform
/e2e/ @grafana/grafana-frontend-platform
/e2e/cloud-plugins-suite/ @grafana/partner-datasources
-/e2e/plugin-e2e/plugin-e2e-api-tests/ @grafana/plugins-platform-frontend
-/e2e/test-plugins/grafana-extensionstest-app/ @grafana/plugins-platform-frontend
+/e2e-playwright/ @grafana/grafana-frontend-platform
+/e2e-playwright/plugin-e2e/ @grafana/oss-big-tent @grafana/partner-datasources
+/e2e-playwright/plugin-e2e/plugin-e2e-api-tests/ @grafana/plugins-platform-frontend
+/e2e-playwright/test-plugins/grafana-extensionstest-app/ @grafana/plugins-platform-frontend
# Packages
/packages/ @grafana/grafana-frontend-platform @grafana/plugins-platform-frontend
@@ -477,6 +479,7 @@
/cypress.config.js @grafana/grafana-frontend-platform
/.levignore.js @grafana/plugins-platform-frontend
playwright.config.ts @grafana/plugins-platform-frontend
+playwright.storybook.config.ts @grafana/grafana-frontend-platform
# public folder
/public/app/api/ @grafana/grafana-frontend-platform
@@ -747,6 +750,7 @@ embed.go @grafana/grafana-as-code
/pkg/kinds/ @grafana/grafana-as-code
/pkg/registry/ @grafana/grafana-as-code
/pkg/registry/apis/ @grafana/grafana-app-platform-squad
+/pkg/registry/apis/folders @grafana/grafana-search-and-storage
/pkg/registry/apis/query @grafana/grafana-datasources-core-services
/pkg/registry/apis/secret @grafana/grafana-operator-experience-squad
/pkg/registry/apis/userstorage @grafana/grafana-app-platform-squad @grafana/plugins-platform-backend
@@ -770,6 +774,7 @@ embed.go @grafana/grafana-as-code
/.github/pr-checks.json @tolzhabayev
/.github/pr-commands.json @tolzhabayev
/.github/renovate.json5 @grafana/frontend-ops
+/.github/actions/check-jobs/action.yml @grafana/grafana-frontend-platform
/.github/actions/setup-enterprise/action.yml @grafana/grafana-backend-group
/.github/actions/setup-grafana-bench/ @Proximyst
/.github/actions/build-package @grafana/grafana-developer-enablement-squad
@@ -796,6 +801,7 @@ embed.go @grafana/grafana-as-code
/.github/workflows/commands.yml @torkelo
/.github/workflows/community-release.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/detect-breaking-changes-* @grafana/plugins-platform-frontend
+/.github/workflows/detect-plugin-extension-changes.yml @grafana/plugins-platform-frontend
/.github/workflows/documentation-ci.yml @grafana/docs-tooling
/.github/workflows/deploy-pr-preview.yml @grafana/docs-tooling
/.github/workflows/feature-toggles-ci.yml @grafana/docs-tooling
@@ -817,6 +823,7 @@ embed.go @grafana/grafana-as-code
/.github/workflows/scripts/json-file-to-job-output.js @grafana/plugins-platform-frontend
/.github/workflows/stale.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/storybook-verification.yml @grafana/grafana-frontend-platform
+/.github/workflows/storybook-verification-playwright.yml @grafana/grafana-frontend-platform
/.github/workflows/update-make-docs.yml @grafana/docs-tooling
/.github/workflows/scripts/kinds/verify-kinds.go @grafana/platform-monitoring
/.github/workflows/scripts/create-security-branch/create-security-branch.sh @grafana/grafana-developer-enablement-squad
@@ -835,6 +842,7 @@ embed.go @grafana/grafana-as-code
/.github/workflows/i18n-crowdin-download.yml @grafana/grafana-frontend-platform
/.github/workflows/i18n-crowdin-create-tasks.yml @grafana/grafana-frontend-platform
/.github/workflows/i18n-verify.yml @grafana/grafana-frontend-platform
+/.github/workflows/deploy-storybook-preview.yml @grafana/grafana-frontend-platform
/.github/workflows/scripts/crowdin/create-tasks.ts @grafana/grafana-frontend-platform
/.github/workflows/pr-go-workspace-check.yml @grafana/grafana-app-platform-squad
/.github/workflows/pr-dependabot-update-go-workspace.yml @grafana/grafana-app-platform-squad
@@ -875,3 +883,7 @@ embed.go @grafana/grafana-as-code
/conf/provisioning/datasources/ @grafana/plugins-platform-backend
/conf/provisioning/plugins/ @grafana/plugins-platform-backend
/conf/provisioning/sample/ @grafana/grafana-git-ui-sync-team
+
+# Security
+/relyance.yaml @grafana/security-team
+/.github/workflows/relyance-scan.yml @grafana/security-team
diff --git a/.github/actions/check-jobs/action.yml b/.github/actions/check-jobs/action.yml
new file mode 100644
index 00000000000..b4551730b96
--- /dev/null
+++ b/.github/actions/check-jobs/action.yml
@@ -0,0 +1,48 @@
+name: Check jobs results
+description: Checks if any jobs have failed and exits with error if failures are found. Use to check the results of matrix test runs.
+inputs:
+ needs:
+ description: JSON string containing the needs context from the workflow
+ required: true
+ failure-message:
+ description: Custom message to display when failures are found
+ required: false
+ default: "One or more jobs have failed"
+ success-message:
+ description: Custom message to display when all jobs pass
+ required: false
+ default: "All jobs passed successfully"
+outputs:
+ any-failed:
+ description: Whether any jobs failed
+ value: ${{ steps.check-jobs.outputs.any-failed }}
+
+runs:
+ using: "composite"
+ steps:
+ - name: Check test suites
+ id: check-jobs
+ shell: bash
+ env:
+ NEEDS: ${{ inputs.needs }}
+ FAILURE_MSG: ${{ inputs.failure-message }}
+ SUCCESS_MSG: ${{ inputs.success-message }}
+ run: |
+ set -euo pipefail
+
+ # Print the needs context, debugging
+ echo "$NEEDS" | jq
+
+ # Extract failures
+ FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
+
+ # Check if there are any failures
+ if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
+ echo "❌ $FAILURE_MSG"
+ echo "Failed suites:"
+ echo "$FAILURES" | jq -r 'to_entries[] | "- \(.key): \(.value)"'
+ echo "any-failed=true" >> "$GITHUB_OUTPUT"
+ exit 1
+ fi
+
+ echo "✅ $SUCCESS_MSG"
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 263a75f43ab..1c62ef810eb 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,11 +8,11 @@ updates:
directories:
- "/"
- "/apps/playlist"
+ - "/apps/secret"
- "/apps/investigations"
- "/pkg/aggregator"
- "/pkg/apimachinery"
- "/pkg/apis/folder"
- - "/pkg/apis/secret"
- "/pkg/apiserver"
- "/pkg/build"
- "/pkg/build/wire"
diff --git a/.github/license_finder.yaml b/.github/license_finder.yaml
index f2fc8a144c4..1b1f5e1df13 100644
--- a/.github/license_finder.yaml
+++ b/.github/license_finder.yaml
@@ -99,7 +99,7 @@
:versions: []
:when: 2025-05-03 13:10:00.000000000 Z
- - :license
- - github.com/grafana/grafana/pkg/apis/secret
+ - github.com/grafana/grafana/apps/secret
- unknown
- :who: Carl Bergquist
:why: repository is owned by Grafana Labs
diff --git a/.github/workflows/core-plugins-build-and-release.yml b/.github/workflows/core-plugins-build-and-release.yml
index 6b05b9863c8..c3c934ea2b6 100644
--- a/.github/workflows/core-plugins-build-and-release.yml
+++ b/.github/workflows/core-plugins-build-and-release.yml
@@ -62,7 +62,7 @@ jobs:
with:
credentials_json: '${{ env.PLUGINS_GOOGLE_CREDENTIALS }}'
- name: 'Set up Cloud SDK'
- uses: 'google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a'
+ uses: 'google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a'
- name: Setup nodejs environment
uses: actions/setup-node@v4
with:
diff --git a/.github/workflows/deploy-storybook-preview.yml b/.github/workflows/deploy-storybook-preview.yml
new file mode 100644
index 00000000000..a1fecce67cb
--- /dev/null
+++ b/.github/workflows/deploy-storybook-preview.yml
@@ -0,0 +1,93 @@
+name: Deploy Storybook preview
+
+on:
+ pull_request:
+ paths:
+ - 'packages/grafana-ui/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions: {}
+
+jobs:
+ deploy-storybook-preview:
+ name: Deploy Storybook preview
+ runs-on: ubuntu-latest
+ # Don't run from forks for the moment. If we find this useful we can do the workflow_run dance
+ # to make it work for forks.
+ if: github.event.pull_request.head.repo.fork == false
+ permissions:
+ contents: read
+ id-token: write
+
+ env:
+ BUCKET_NAME: grafana-storybook-previews
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Cache node_modules
+ uses: actions/cache@v4
+ with:
+ path: |
+ node_modules
+ key: node_modules-${{ hashFiles('yarn.lock') }}
+ restore-keys: |
+ node_modules-
+
+ - name: Install dependencies
+ env:
+ # If the PR isn't from a fork then don't use the slower yarn checks
+ YARN_ENABLE_HARDENED_MODE: ${{ github.event.pull_request.head.repo.fork == false && '1' || '0' }}
+ run: yarn install --immutable
+
+ - name: Build storybook
+ run: yarn storybook:build
+
+ # Create the GCS folder name for the preview. Creates a consistent name for all deploys for the PR.
+ # Matches format of `pr__`.
+ # Where `SANITIZED_BRANCH` is the branch name with only alphanumeric and hyphens, limited to 30 characters.
+ - name: Create deploy name
+ id: create-deploy-name
+ env:
+ BRANCH_NAME: ${{ github.event.pull_request.head.ref }}
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ run: |
+ # Convert branch name to only contain alphanumeric and hyphens
+ SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | tr -cs "[:alnum:]-" "-" | sed "s/^-//;s/-$//")
+
+ # Check if SANITIZED_BRANCH is empty and fail if it is
+ if [ -z "$SANITIZED_BRANCH" ]; then
+ echo "Error: Branch name resulted in empty string after sanitization"
+ exit 1
+ fi
+
+ echo "deploy-name=pr_${PR_NUMBER}_${SANITIZED_BRANCH:0:30}" >> "$GITHUB_OUTPUT"
+
+ - name: Upload Storybook
+ uses: grafana/shared-workflows/actions/push-to-gcs@main
+ with:
+ environment: prod
+ bucket: ${{ env.BUCKET_NAME }}
+ bucket_path: ${{ steps.create-deploy-name.outputs.deploy-name }}
+ path: packages/grafana-ui/dist/storybook
+ service_account: github-gf-storybook-preview@grafanalabs-workload-identity.iam.gserviceaccount.com
+ parent: false
+
+ - name: Write summary
+ env:
+ DEPLOY_NAME: ${{ steps.create-deploy-name.outputs.deploy-name }}
+ run: |
+ echo "## Storybook preview deployed! 🚀" >> $GITHUB_STEP_SUMMARY
+ echo "Check it out at https://storage.googleapis.com/${BUCKET_NAME}/${DEPLOY_NAME}/index.html" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/detect-breaking-changes-levitate.yml b/.github/workflows/detect-breaking-changes-levitate.yml
index a4328970ff7..8a0d3ecc70d 100644
--- a/.github/workflows/detect-breaking-changes-levitate.yml
+++ b/.github/workflows/detect-breaking-changes-levitate.yml
@@ -158,13 +158,15 @@ jobs:
- id: 'auth'
uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f'
+ if: github.event.pull_request.head.repo.full_name == github.repository
with:
workload_identity_provider: projects/304398677251/locations/global/workloadIdentityPools/github/providers/github-provider
service_account: github-plugins-data-levitate@grafanalabs-workload-identity.iam.gserviceaccount.com
project_id: 'grafanalabs-global'
- name: 'Set up Cloud SDK'
- uses: 'google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a'
+ uses: 'google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a'
+ if: github.event.pull_request.head.repo.full_name == github.repository
with:
version: '>= 363.0.0'
project_id: 'grafanalabs-global'
@@ -175,6 +177,7 @@ jobs:
run: ./scripts/check-breaking-changes.sh
env:
FORCE_COLOR: 3
+ IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} # used in check-breaking-changes.sh and levitate-parse-json-report.js
- name: Persisting the check output
run: |
@@ -199,6 +202,7 @@ jobs:
permissions:
contents: read
id-token: write
+ if: github.event.pull_request.head.repo.full_name == github.repository
steps:
- id: get-secrets
diff --git a/.github/workflows/detect-plugin-extension-changes.yml b/.github/workflows/detect-plugin-extension-changes.yml
new file mode 100644
index 00000000000..b5ab96725d9
--- /dev/null
+++ b/.github/workflows/detect-plugin-extension-changes.yml
@@ -0,0 +1,156 @@
+---
+name: Detect Plugin Extension Changes
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions: {}
+
+on:
+ pull_request:
+ branches:
+ - 'main'
+ paths:
+ - 'packages/**'
+ - 'public/**'
+
+env:
+ # Space-separated list of keywords referring to plugin extensions
+ PLUGIN_EXTENSION_KEYWORDS: "usePluginLinks, usePluginComponent, usePluginComponents, usePluginFunctions, PluginExtensionPoints"
+
+jobs:
+ detect-plugin-extension-changes:
+ name: Detect Plugin Extension Changes
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
+ if: github.event.pull_request.head.repo.full_name == github.repository
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+
+ - name: Check for plugin extension changes
+ id: check-changes
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { execSync } = require('child_process');
+ const fs = require('fs');
+
+ // Plugin extension keywords from environment
+ const keywords = process.env.PLUGIN_EXTENSION_KEYWORDS.split(',');
+ const baseSha = '${{ github.event.pull_request.base.sha }}';
+ const headSha = '${{ github.event.pull_request.head.sha }}';
+
+ console.log('Checking for plugin extension changes...');
+ console.log('Keywords:', keywords);
+
+ // Get changed files in packages/ and public/ directories
+ let changedFiles = [];
+ const diffOutput = execSync(
+ `git diff --name-only ${baseSha}...${headSha} -- packages/ public/`,
+ { encoding: 'utf8' }
+ ).trim();
+
+ if (diffOutput) {
+ changedFiles = diffOutput.split('\n').filter(file => {
+ // Validate file path and ensure it's in target directories
+ return file.match(/^(packages\/|public\/)/) &&
+ file.match(/^[a-zA-Z0-9._/-]+$/) &&
+ fs.existsSync(file);
+ });
+ }
+
+ console.log('Changed files to check:', changedFiles);
+
+ // Check each file for plugin extension keywords
+ const filesWithChanges = new Set();
+ let hasPluginExtensionChanges = false;
+
+ for (const file of changedFiles) {
+ try {
+ // Get the diff for this specific file
+ const fileDiff = execSync(
+ `git diff ${baseSha}...${headSha} -- "${file}"`,
+ { encoding: 'utf8' }
+ );
+
+ // Check if any keywords are in the diff
+ for (const keyword of keywords) {
+ if (fileDiff.includes(keyword)) {
+ console.log(`Found ${keyword} in ${file}`);
+ filesWithChanges.add(file);
+ hasPluginExtensionChanges = true;
+ break; // Found at least one keyword, move to next file
+ }
+ }
+ } catch (error) {
+ console.log(`Error checking file ${file}:`, error.message);
+ }
+ }
+
+ // Set outputs
+ const filesArray = Array.from(filesWithChanges);
+ const formattedFiles = filesArray.length > 0
+ ? '`' + filesArray.join('`\\n- `') + '`'
+ : '';
+
+ core.setOutput('plugin_extension_changes', hasPluginExtensionChanges.toString());
+ core.setOutput('formatted_changed_files', formattedFiles);
+
+ if (hasPluginExtensionChanges) {
+ console.log('The following files have changes that may affect plugin extensions:');
+ console.log(filesArray);
+ } else {
+ console.log('No changes detected in core Grafana extensions or extension points.');
+ }
+
+ - name: Send Slack Message via Payload
+ id: slack
+ if: steps.check-changes.outputs.plugin_extension_changes == 'true'
+ uses: grafana/shared-workflows/actions/send-slack-message@0941e3408fa4789fec9062c44a2a9e1832146ba6 #v2.0.1
+ with:
+ method: chat.postMessage
+ payload-templated: true
+ payload: |
+ {
+ "channel": "C031SLFH6G0",
+ "text": "Plugin Extension changes in core Grafana *PR:* <${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }} :information_source:",
+ "icon_emoji": ":grot:",
+ "username": "Plugin Extension Bot",
+ "blocks": [
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "*Plugin Extensions:* possible changes to extension points in core Grafana."
+ }
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "*PR:* <${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }}>\n*Job:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Job>"
+ }
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "*File(s) with changes:*\n- ${{ steps.check-changes.outputs.formatted_changed_files }}"
+ }
+ },
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "*What to do?*\nMake sure that:\n- All extension point ids start with `grafana/`\n- All extension point ids are exposed via \n- Core Grafana is not registering extensions to extension points offered by plugins"
+ }
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/.github/workflows/frontend-lint.yml b/.github/workflows/frontend-lint.yml
index e5ceb117eea..fb0362bb580 100644
--- a/.github/workflows/frontend-lint.yml
+++ b/.github/workflows/frontend-lint.yml
@@ -16,6 +16,7 @@ jobs:
contents: read
outputs:
changed: ${{ steps.detect-changes.outputs.frontend }}
+ prettier: ${{ steps.detect-changes.outputs.frontend == 'true' || steps.detect-changes.outputs.docs == 'true' }}
steps:
- uses: actions/checkout@v4
with:
@@ -34,7 +35,7 @@ jobs:
id-token: write
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# the `lint-frontend-prettier-enterprise` workflow will run instead
- if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.changed == 'true'
+ if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.prettier == 'true'
name: Lint
runs-on: ubuntu-latest
steps:
@@ -55,7 +56,7 @@ jobs:
contents: read
id-token: write
# Run this workflow for non-PR events (like pushes to `main` or `release-*`) OR for internal PRs (PRs not from forks)
- if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.changed == 'true'
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.prettier == 'true'
name: Lint
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/i18n-crowdin-create-tasks.yml b/.github/workflows/i18n-crowdin-create-tasks.yml
index 6ecaa883e01..e26d7806c5e 100644
--- a/.github/workflows/i18n-crowdin-create-tasks.yml
+++ b/.github/workflows/i18n-crowdin-create-tasks.yml
@@ -2,10 +2,9 @@ name: Crowdin automatic task management
on:
workflow_dispatch:
- # once a week on Sunday at midnight
- # TODO enable once we're ready to create tasks automatically
- # schedule:
- # - cron: "0 0 * * 0"
+ # once a month on the first day of the month at midnight
+ schedule:
+ - cron: "0 0 1 * *"
jobs:
create-tasks-in-crowdin:
diff --git a/.github/workflows/i18n-crowdin-download.yml b/.github/workflows/i18n-crowdin-download.yml
index 1c1f87efc40..e8e04c22029 100644
--- a/.github/workflows/i18n-crowdin-download.yml
+++ b/.github/workflows/i18n-crowdin-download.yml
@@ -7,6 +7,7 @@ on:
jobs:
download-sources-from-crowdin:
+ if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-download.yml@main
with:
crowdin_project_id: 5
diff --git a/.github/workflows/i18n-crowdin-upload.yml b/.github/workflows/i18n-crowdin-upload.yml
index c3a48f97481..b61a7538bf0 100644
--- a/.github/workflows/i18n-crowdin-upload.yml
+++ b/.github/workflows/i18n-crowdin-upload.yml
@@ -14,6 +14,7 @@ on:
jobs:
upload-sources-to-crowdin:
+ if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-upload.yml@main
with:
crowdin_project_id: 5
diff --git a/.github/workflows/pr-e2e-tests.yml b/.github/workflows/pr-e2e-tests.yml
index ec74716f7e3..5e7d116d0c2 100644
--- a/.github/workflows/pr-e2e-tests.yml
+++ b/.github/workflows/pr-e2e-tests.yml
@@ -7,12 +7,17 @@ on:
- main
- release-*.*.*
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
+# TODO: re-enable this before merging
+# concurrency:
+# group: ${{ github.workflow }}-${{ github.ref }}
+# cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
permissions: {}
+env:
+ ACTIONS_STEP_DEBUG: true
+ RUNNER_DEBUG: 1
+
jobs:
detect-changes:
name: Detect whether code changed
@@ -44,22 +49,56 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
- path: ./grafana
persist-credentials: false
- - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
+
+ # TODO: add a cleanup workflow to remove the cache when the PR is closed
+ # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy
+ # TODO: maybe we could just use the cache to store the build, instead of uploading as an artifact?
+ - uses: actions/cache@v4
+ id: cache
+ with:
+ key: "build-grafana-${{ runner.os }}-${{ hashFiles('yarn.lock', 'public/*', 'packages/*', 'pkg/**/*.go', '**/go.mod', '**/go.sum', '!**_test.go', '!**.test.ts', '!**.test.tsx') }}"
+ path: |
+ build-dir
+
+ # If no cache hit, build Grafana
+ - name: Build Grafana
+ if: steps.cache.outputs.cache-hit != 'true'
+ uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
- args: go -C grafana run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir="${PWD}/grafana" > out.txt
- - run: mv "$(cat out.txt)" grafana.tar.gz
- - run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT"
+ args: go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir="${PWD}" > out.txt
+ - name: Cat built artifact
+ if: steps.cache.outputs.cache-hit != 'true'
+ run: cat out.txt
+ - name: Move built artifact
+ if: steps.cache.outputs.cache-hit != 'true'
+ run: |
+ mkdir -p build-dir
+ mv "$(cat out.txt)" build-dir/grafana.tar.gz
+
+ # If cache hit, validate the artifact is present
+ - name: Validate artifact
+ if: steps.cache.outputs.cache-hit == 'true'
+ run: |
+ if [ ! -f build-dir/grafana.tar.gz ]; then
+ echo "Error: build-dir/grafana.tar.gz not found in cache"
+ exit 1
+ fi
+
+ - name: Set artifact name
+ run: echo "artifact=grafana-server-${{github.run_number}}" >> "$GITHUB_OUTPUT"
id: artifact
- - uses: actions/upload-artifact@v4
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
id: upload
with:
retention-days: 1
name: ${{ steps.artifact.outputs.artifact }}
- path: grafana.tar.gz
+ path: build-dir/grafana.tar.gz
+ # TODO: we won't need this when we only have playwright
build-e2e-runner:
needs: detect-changes
if: needs.detect-changes.outputs.changed == 'true'
@@ -159,6 +198,119 @@ jobs:
path: videos
retention-days: 1
+ run-playwright-tests:
+ needs:
+ - build-grafana
+ name: Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }})
+ runs-on: ubuntu-latest-8-cores
+ permissions:
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ shard: [1, 2, 3, 4, 5, 6, 7, 8]
+ shardTotal: [8]
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ - uses: actions/download-artifact@v4
+ with:
+ name: ${{ needs.build-grafana.outputs.artifact }}
+ - name: Run E2E tests
+ uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
+ with:
+ verb: run
+ args: go run ./pkg/build/e2e-playwright --package=grafana.tar.gz --shard=${{ matrix.shard }}/${{ matrix.shardTotal }} --blob-dir=./blob-report
+ - uses: actions/upload-artifact@v4
+ if: success() || failure()
+ with:
+ name: playwright-blob-${{ github.run_number }}-${{ matrix.shard }}
+ path: ./blob-report
+ retention-days: 1
+
+ required-playwright-tests:
+ needs:
+ - run-playwright-tests
+ - build-grafana
+ if: ${{ !cancelled() }}
+ name: All Playwright tests complete
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+
+ - name: Download blob reports from GitHub Actions Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: blobs
+ pattern: playwright-blob-*
+ merge-multiple: true
+
+ - name: Check blob reports
+ run: |
+ if [ ! "$(ls -A ./blobs)" ]; then
+ echo "Error: No blob reports found in ./blobs directory"
+ echo "Did the Playwright tests run at all?"
+ exit 1
+ fi
+ echo "Found blob reports in ./blobs:"
+ ls -lah ./blobs
+
+ - name: Merge into HTML Report
+ run: npx playwright merge-reports --reporter html ./blobs
+
+ - name: Merge into JSON Report
+ env:
+ PLAYWRIGHT_JSON_OUTPUT_NAME: /tmp/playwright-results.json
+ run: npx playwright merge-reports --reporter=json ./blobs
+
+ - name: Bench report
+ run: |
+ docker run --rm \
+ --volume="/tmp/playwright-results.json:/home/bench/tests/playwright-results.json" \
+ us-docker.pkg.dev/grafanalabs-global/docker-grafana-bench-prod/grafana-bench:v0.5.1 report \
+ --grafana-url "http://localhost:3000" \
+ --grafana-version "CI- ${{ github.sha }}" \
+ --test-suite-name "FrontendCore" \
+ --report-input playwright \
+ --report-output log \
+ --log-level DEBUG \
+ /home/bench/tests/playwright-results.json
+
+ - name: Upload HTML report
+ uses: actions/upload-artifact@v4
+ with:
+ name: playwright-html-${{ github.run_number }}
+ path: playwright-report
+ retention-days: 7
+
+ - name: Check test suites
+ id: check-jobs
+ uses: ./.github/actions/check-jobs
+ continue-on-error: true # Failure will be reported on Show test results step
+ with:
+ needs: ${{ toJson(needs) }}
+ failure-message: "One or more E2E test suites have failed"
+ success-message: "All E2E test suites completed successfully"
+
+ - name: Show test results
+ env:
+ FAILED: ${{ steps.check-jobs.outputs.any-failed }}
+ # sed removes the leading `../../src/` from the paths
+ run: |
+ npx playwright merge-reports --reporter list ./all-blob-reports | sed 's|\(\.\./\)\{1,\}src/|/|g'
+ if [ "$FAILED" = "true" ]; then
+ exit 1
+ fi
+
run-a11y-test:
needs:
- build-grafana
@@ -193,6 +345,7 @@ jobs:
required-e2e-tests:
needs:
- run-e2e-tests
+ - build-grafana
# a11y test is not listed on purpose: it is not an important E2E test.
# It is also totally fine to fail right now.
# always() is the best function here.
@@ -203,13 +356,13 @@ jobs:
name: All E2E tests complete
runs-on: ubuntu-latest
steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
- name: Check test suites
- env:
- NEEDS: ${{ toJson(needs) }}
- run: |
- FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
- echo "$FAILURES"
- if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
- exit 1
- fi
- echo "All OK!"
+ uses: ./.github/actions/check-jobs
+ with:
+ needs: ${{ toJson(needs) }}
+ failure-message: "One or more E2E test suites have failed"
+ success-message: "All E2E test suites completed successfully"
diff --git a/.github/workflows/publish-artifact.yml b/.github/workflows/publish-artifact.yml
index 1cc650858a7..45aa1d79445 100644
--- a/.github/workflows/publish-artifact.yml
+++ b/.github/workflows/publish-artifact.yml
@@ -48,7 +48,7 @@ jobs:
path: ./artifact
- name: Log in to GCS
id: login-to-gcs
- uses: grafana/shared-workflows/actions/login-to-gcs@login-to-gcs/v0.2.1
+ uses: grafana/shared-workflows/actions/login-to-gcs@main
with:
environment: ${{ inputs.environment }}
service_account: ${{ inputs.service-account }}
@@ -58,7 +58,7 @@ jobs:
find ./artifact -mindepth 2 -maxdepth 2 -exec cp -r {} out/ \;
ls -al out
- name: Upload artifacts
- uses: grafana/shared-workflows/actions/push-to-gcs@push-to-gcs-v0.2.0
+ uses: grafana/shared-workflows/actions/push-to-gcs@main
with:
bucket: ${{ inputs.bucket }}
environment: ${{ inputs.environment }}
@@ -66,3 +66,4 @@ jobs:
path: out
bucket_path: ${{ inputs.bucket-path }}
service_account: ${{ inputs.service-account }}
+ gzip: false
diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
index 54c81f1091f..35b8a219d62 100644
--- a/.github/workflows/release-build.yml
+++ b/.github/workflows/release-build.yml
@@ -186,5 +186,5 @@ jobs:
bucket: grafana-prerelease
pattern: artifacts-*
run-id: ${{ github.run_id }}
- bucket-path: ${{ needs.setup.outputs.version }}
+ bucket-path: ${{ needs.setup.outputs.version }}_${{ github.run_id }}
environment: prod
diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml
index 06a644f5843..2c43ae43de4 100644
--- a/.github/workflows/release-pr.yml
+++ b/.github/workflows/release-pr.yml
@@ -208,7 +208,7 @@ jobs:
if: ${{ inputs.bump == true || inputs.bump == 'true' }}
run: |
git add package.json lerna.json yarn.lock packages public
- test -e e2e/test-plugins && git add e2e/test-plugins
+ test -e e2e-playwright/test-plugins && git add e2e-playwright/test-plugins
git commit -m "Update version to $VERSION"
- name: Git push
diff --git a/.github/workflows/relyance-scan.yml b/.github/workflows/relyance-scan.yml
new file mode 100644
index 00000000000..29d68e00416
--- /dev/null
+++ b/.github/workflows/relyance-scan.yml
@@ -0,0 +1,33 @@
+name: Relyance Compliance Inspection
+on:
+ schedule:
+ - cron: '0 0 * * *' # Run daily at 00:00 UTC
+ workflow_dispatch: # Allow for manual trigger
+
+jobs:
+ relyance-compliance-inspector:
+ permissions:
+ contents: read
+ id-token: write # Needed for Vault access
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: Get API key
+ id: vault-secrets
+ uses: grafana/shared-workflows/actions/get-vault-secrets@5d7e361bc7e0a183cde8afe9899fb7b596d2659b # get-vault-secrets-v1.2.0
+ with:
+ repo_secrets: |
+ API_KEY=relyance:API_KEY
+
+ - name: Run Relyance scan
+ env:
+ API_KEY: "${{ fromJSON(steps.vault-secrets.outputs.secrets).API_KEY }}"
+ run: |
+ docker pull gcr.io/relyance-ext/compliance_inspector:release && \
+ docker run --rm -v ${{ github.workspace }}:/repo --env "API_KEY=${{ env.API_KEY }}" gcr.io/relyance-ext/compliance_inspector:release
diff --git a/.github/workflows/run-dashboard-search-e2e.yml b/.github/workflows/run-dashboard-search-e2e.yml
index 8554f7549a6..6eebaf9320a 100644
--- a/.github/workflows/run-dashboard-search-e2e.yml
+++ b/.github/workflows/run-dashboard-search-e2e.yml
@@ -64,7 +64,7 @@ jobs:
tools/
public/
conf/
- e2e/test-plugins/
+ e2e-playwright/test-plugins/
devenv/
key: ${{ runner.os }}-grafana-${{ hashFiles('go.mod', 'package-lock.json', 'Makefile', 'pkg/storage/**/*.go', 'public/app/features/search/**/*.ts', 'public/app/features/search/**/*.tsx') }}
# only rebuild grafana if search files have changed ( or dependencies )
@@ -116,7 +116,7 @@ jobs:
tools/
public/
conf/
- e2e/test-plugins/
+ e2e-playwright/test-plugins/
devenv/
key: ${{ runner.os }}-grafana-${{ hashFiles('go.mod', 'package-lock.json', 'Makefile', 'pkg/storage/**/*.go', 'public/app/features/search/**/*.ts', 'public/app/features/search/**/*.tsx') }}
- name: Set the step name
diff --git a/.github/workflows/storybook-verification-playwright.yml b/.github/workflows/storybook-verification-playwright.yml
new file mode 100644
index 00000000000..e3924a67a85
--- /dev/null
+++ b/.github/workflows/storybook-verification-playwright.yml
@@ -0,0 +1,47 @@
+name: Verify Storybook (Playwright)
+
+on:
+ pull_request:
+ paths:
+ - 'packages/grafana-ui/**'
+ - 'e2e-playwright/storybook/**'
+ - '!docs/**'
+ - '!*.md'
+ push:
+ branches:
+ - main
+ paths:
+ - 'packages/grafana-ui/**'
+ - 'e2e-playwright/storybook/**'
+ - '!docs/**'
+ - '!*.md'
+
+permissions: {}
+
+jobs:
+ verify-storybook:
+ name: Verify Storybook (Playwright)
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --immutable
+
+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps
+
+ - name: Run Storybook and E2E tests
+ run: yarn e2e:playwright:storybook
diff --git a/.gitignore b/.gitignore
index ccc42239a87..7457c8148b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -237,4 +237,4 @@ public/app/plugins/**/dist/
# Mock service worker used for fake API responses in frontend development
public/mockServiceWorker.js
-/e2e/test-plugins/*/dist
+/e2e-playwright/test-plugins/*/dist
diff --git a/.golangci.yml b/.golangci.yml
index 5bb4a5e3167..5a534ee8ec2 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -83,6 +83,14 @@ linters:
deny:
- pkg: github.com/grafana/grafana/pkg
desc: apps/playlist is not allowed to import grafana core
+ apps-secret:
+ list-mode: lax
+ files:
+ - ./apps/secret/*
+ - ./apps/secret/**/*
+ deny:
+ - pkg: github.com/grafana/grafana/pkg
+ desc: apps/secret is not allowed to import grafana core
coreplugins:
files:
- '**/pkg/tsdb/grafana-pyroscope-datasource/*'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4527ac3487d..12a43e07e98 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,29 +1,56 @@
-# Contributing to Grafana
+# Contribute to Grafana
Thank you for your interest in contributing to Grafana! We welcome all people who want to contribute in a healthy and constructive manner within our community. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md).
-This document is a guide to help you through the process of contributing to Grafana.
+This document is a guide to help you through the process of making technical contributions to Grafana.
-## Become a contributor
+Whether you're a new contributer or a seasoned veteran we hope these resources help you connect with the community:
-You can contribute to Grafana in several ways. Here are some examples:
+Interact and be heard:
-- Contribute to the Grafana codebase.
-- Report and triage bugs.
-- Develop community plugins and dashboards.
-- Write technical documentation and blog posts, for users and contributors.
-- Organize meetups and user groups in your local area.
-- Help others by answering questions about Grafana.
+- Forums: Do you have a problem, question, or curiosity? Visit our [forums](https://gra.fan/fromgithubtoforums) for a reservoir of knowledge- submit your own questions and answers!
+- Meetups: Craving in-person connections without the long journeys? [Join your local Grafana & Friends meetup group](https://gra.fan/githubtomeetup)!
+- Community Slack: Eager for real-time connections with fellow users? Begin a conversation on [Slack](https://gra.fan/githubtoslack).
+ Learn:
+- YouTube: From getting started to exploring newer projects like Pyroscope and Beyla, the [Grafana YouTube channel](https://gra.fan/githubtoyoutube) has what you need to get started!
+- Meetups: Join a [group near you](https://gra.fan/githubtomeetup) to learn from local experts and ask questions in real time.
+ Share your story:
+- Meetups and blogs: We’d love to feature your OSS Grafana Labs use case or story at an upcoming Grafana & Friends meetup or on the Grafana blog! Submit your idea [here](https://gra.fan/githubtocca) and we’ll connect with you on next steps if accepted.
+
+## Make technical contributions
+
+We welcome your technical contributions! Here are some examples:
+
+- Contribute to the Grafana codebase- check out these [help-wanted issues](<(https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)>)
+- Develop community [plugins](https://grafana.com/developers/plugin-tools)
+- Report [bugs](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml)
+- [Triage issues](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/triage-issues.md)
+- Report [security vulnerabilities](https://github.com/grafana/grafana/security/policy)
+- Submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md)
+- Write [technical documentation](https://github.com/grafana/grafana/blob/4414b92e93440cc9ed0f281989ee71dc16216a15/contribute/documentation/README.md)
**Please note:** We do not currently accept contributions for translations. Please do not submit pull requests translating grafana.json files - they will be rejected. We do accept contributions to mark up phrases for translation. See [Internationalization](contribute/internationalization.md).
-For more ways to contribute, check out the [Open Source Guides](https://opensource.guide/how-to-contribute/).
+### Your first contribution
+
+Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`.
+
+- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete.
+- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity.
+
+If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md).
+
+When you're ready to contribute, it's time to [create a pull request](/contribute/create-pull-request.md).
+
+### Develop a plugin
+
+Developing a Grafana plugin is a fantastic way to share your unique ideas with the community, extend the platform’s capabilities, and make a real impact on how people visualize and understand their data. Check out our guide to creating [plugins](https://grafana.com/developers/plugin-tools)
### Report bugs
Before submitting a new issue, try to make sure someone hasn't already reported the problem. Look through the [existing issues](https://github.com/grafana/grafana/issues) for similar issues.
-Report a bug by submitting a [bug report](https://github.com/grafana/grafana/issues/new?labels=type%3A+bug&template=1-bug_report.md). Make sure that you provide as much information as possible on how to reproduce the bug.
+Report a bug by submitting a [bug report](https://github.com/grafana/grafana/issues/new?template=0-bug-report.yaml). Make sure that you provide as much information as possible on how to reproduce the bug.
Follow the issue template and add additional information that will help us replicate the problem.
@@ -38,42 +65,25 @@ For a dashboard related issues:
For authentication and alerting Grafana server logs are useful.
-#### Security issues
-
-If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details.
-
-### Suggest enhancements
-
-If you have an idea of how to improve Grafana, submit a [feature request](https://github.com/grafana/grafana/issues/new?assignees=&labels=type%2Ffeature-request&projects=&template=1-feature_requests.md).
-
-We want to make Grafana accessible to even more people. Submit an [accessibility issue](https://github.com/grafana/grafana/issues/new?labels=type%3A+accessibility&template=3-accessibility.md) to help us understand what we can improve.
-
-### Write documentation
-
-To edit or write technical content, refer to [Contribute to our documentation](/contribute/documentation/README.md). We welcome your expertise and input as our body of technical content grows.
-
### Triage issues
If you don't have the knowledge or time to code, consider helping with _issue triage_. The community will thank you for saving them time by spending some of yours.
Read more about the ways you can [Triage issues](/contribute/triage-issues.md).
-### Answering questions
+#### Security issues
-If you have a question and you can't find the answer in the [documentation](https://grafana.com/docs/), the next step is to ask it on the [community site](https://community.grafana.com/).
+If you believe you've found a security vulnerability, please read our [security policy](https://github.com/grafana/grafana/security/policy) for more details on reporting.
-It's important to us to help these users, and we'd love your help. Sign up to our [community site](https://community.grafana.com/), and start helping other Grafana users by answering their questions.
+### Suggest enhancements
-### Your first contribution
+If you have an idea of how to improve Grafana, submit a [feature request](https://github.com/grafana/grafana/issues/new?template=1-feature_requests.md).
-Unsure where to begin contributing to Grafana? Start by browsing issues labeled `beginner friendly` or `help wanted`.
+We want to make Grafana accessible to even more people. Submit an [accessibility issue](https://github.com/grafana/grafana/issues/new?template=2-accessibility.md) to help us understand what we can improve.
-- [Beginner-friendly](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) issues are generally straightforward to complete.
-- [Help wanted](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues are problems we would like the community to help us with regardless of complexity.
+### Write documentation
-If you're looking to make a code change, see how to set up your environment for [local development](contribute/developer-guide.md).
-
-When you're ready to contribute, it's time to [create a pull request](/contribute/create-pull-request.md).
+To edit or write technical content, refer to [Contribute to our documentation](/contribute/documentation/README.md). We welcome your expertise and input as our body of technical content grows.
#### Contributor License Agreement (CLA)
diff --git a/Dockerfile b/Dockerfile
index d98bc6db4e6..4de7a9b5b09 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -71,7 +71,6 @@ COPY .citools .citools
# Include vendored dependencies
COPY pkg/util/xorm pkg/util/xorm
-COPY pkg/apis/secret pkg/apis/secret
COPY pkg/apiserver pkg/apiserver
COPY pkg/apimachinery pkg/apimachinery
COPY pkg/build pkg/build
@@ -83,6 +82,7 @@ COPY pkg/storage/unified/apistore pkg/storage/unified/apistore
COPY pkg/semconv pkg/semconv
COPY pkg/aggregator pkg/aggregator
COPY apps/playlist apps/playlist
+COPY apps/secret apps/secret
COPY apps/investigations apps/investigations
COPY apps/advisor apps/advisor
COPY apps/dashboard apps/dashboard
diff --git a/Makefile b/Makefile
index 7973fd5f679..df23645fe0b 100644
--- a/Makefile
+++ b/Makefile
@@ -471,7 +471,7 @@ protobuf: ## Compile protobuf definitions
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.5
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0
buf generate pkg/plugins/backendplugin/pluginextensionv2 --template pkg/plugins/backendplugin/pluginextensionv2/buf.gen.yaml
- buf generate pkg/apis/secret/v0alpha1/decrypt --template pkg/apis/secret/v0alpha1/decrypt/buf.gen.yaml
+ buf generate apps/secret/decrypt/v1beta1 --template apps/secret/decrypt/v1beta1/buf.gen.yaml
buf generate pkg/storage/unified/proto --template pkg/storage/unified/proto/buf.gen.yaml
buf generate pkg/services/authz/proto/v1 --template pkg/services/authz/proto/v1/buf.gen.yaml
buf generate pkg/services/ngalert/store/proto/v1 --template pkg/services/ngalert/store/proto/v1/buf.gen.yaml
diff --git a/apps/advisor/Makefile b/apps/advisor/Makefile
index 7a5f1c99365..b8b335bfa68 100644
--- a/apps/advisor/Makefile
+++ b/apps/advisor/Makefile
@@ -1,3 +1,22 @@
+APP_SDK_VERSION := v0.39.2
+APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
+APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk
+
+.PHONY: install-app-sdk
+install-app-sdk: $(APP_SDK_BIN) ## Install the Grafana App SDK
+
+$(APP_SDK_BIN):
+ @echo "Installing Grafana App SDK version $(APP_SDK_VERSION)"
+ @mkdir -p $(APP_SDK_DIR)
+ # The only way to install specific versions of binaries using `go install`
+ # is by setting GOBIN to the directory you want to install the binary to.
+ GOBIN=$(APP_SDK_DIR) go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@$(APP_SDK_VERSION)
+ @touch $@
+
+.PHONY: update-app-sdk
+update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
+ go get github.com/grafana/grafana-app-sdk@$(APP_SDK_VERSION)
+
.PHONY: generate
-generate:
- @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
+generate: ## Run Grafana App SDK code generation
+ @$(APP_SDK_BIN) generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
diff --git a/apps/advisor/go.mod b/apps/advisor/go.mod
index 45a7ed0b51e..65832aabb4b 100644
--- a/apps/advisor/go.mod
+++ b/apps/advisor/go.mod
@@ -3,8 +3,8 @@ module github.com/grafana/grafana/apps/advisor
go 1.24.4
require (
- github.com/grafana/grafana-app-sdk v0.39.0
- k8s.io/apimachinery v0.33.1
+ github.com/grafana/grafana-app-sdk v0.39.2
+ k8s.io/apimachinery v0.33.2
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -33,7 +33,7 @@ require (
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/authlib v0.0.0-20250515162837-2f4a8263eabb // indirect
- github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -79,9 +79,9 @@ require (
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.33.1 // indirect
- k8s.io/apiextensions-apiserver v0.33.1 // indirect
- k8s.io/client-go v0.33.1 // indirect
+ k8s.io/api v0.33.2 // indirect
+ k8s.io/apiextensions-apiserver v0.33.2 // indirect
+ k8s.io/client-go v0.33.2 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum
index e7629867703..90b34992392 100644
--- a/apps/advisor/go.sum
+++ b/apps/advisor/go.sum
@@ -63,11 +63,14 @@ github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1
github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
github.com/grafana/grafana-app-sdk v0.35.1/go.mod h1:Zx5MkVppYK+ElSDUAR6+fjzOVo6I/cIgk+ty+LmNOxI=
github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
github.com/grafana/grafana-app-sdk/logging v0.29.0 h1:mgbXaAf33aFwqwGVeaX30l8rkeAJH0iACgX5Rn6YkN4=
github.com/grafana/grafana-app-sdk/logging v0.29.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grafana/grafana-app-sdk/logging v0.35.0/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
@@ -302,21 +305,25 @@ k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
+k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/check_metadata_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/check_metadata_gen.go
index 4b385514d97..0150b059719 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/check_metadata_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/check_metadata_gen.go
@@ -24,5 +24,8 @@ type CheckMetadata struct {
// NewCheckMetadata creates a new CheckMetadata object.
func NewCheckMetadata() *CheckMetadata {
- return &CheckMetadata{}
+ return &CheckMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/check_object_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/check_object_gen.go
index aca8c2876d6..5708bba88d6 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/check_object_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/check_object_gen.go
@@ -18,8 +18,11 @@ import (
type Check struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
- Spec CheckSpec `json:"spec" yaml:"spec"`
- CheckStatus CheckStatus `json:"status" yaml:"status"`
+
+ // Spec is the spec of the Check
+ Spec CheckSpec `json:"spec" yaml:"spec"`
+
+ Status CheckStatus `json:"status" yaml:"status"`
}
func (o *Check) GetSpec() any {
@@ -37,14 +40,14 @@ func (o *Check) SetSpec(spec any) error {
func (o *Check) GetSubresources() map[string]any {
return map[string]any{
- "status": o.CheckStatus,
+ "status": o.Status,
}
}
func (o *Check) GetSubresource(name string) (any, bool) {
switch name {
case "status":
- return o.CheckStatus, true
+ return o.Status, true
default:
return nil, false
}
@@ -57,7 +60,7 @@ func (o *Check) SetSubresource(name string, value any) error {
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type CheckStatus", value)
}
- o.CheckStatus = cast
+ o.Status = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
@@ -219,6 +222,20 @@ func (o *Check) DeepCopyObject() runtime.Object {
return o.Copy()
}
+func (o *Check) DeepCopy() *Check {
+ cpy := &Check{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *Check) DeepCopyInto(dst *Check) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
// Interface compliance compile-time check
var _ resource.Object = &Check{}
@@ -262,5 +279,41 @@ func (o *CheckList) SetItems(items []resource.Object) {
}
}
+func (o *CheckList) DeepCopy() *CheckList {
+ cpy := &CheckList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *CheckList) DeepCopyInto(dst *CheckList) {
+ resource.CopyObjectInto(dst, o)
+}
+
// Interface compliance compile-time check
var _ resource.ListObject = &CheckList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *CheckSpec) DeepCopy() *CheckSpec {
+ cpy := &CheckSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *CheckSpec) DeepCopyInto(dst *CheckSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of CheckStatus
+func (s *CheckStatus) DeepCopy() *CheckStatus {
+ cpy := &CheckStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies CheckStatus into another CheckStatus object
+func (s *CheckStatus) DeepCopyInto(dst *CheckStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
index b77811fefc2..8716958ce02 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
@@ -3,16 +3,18 @@
package v0alpha1
// +k8s:openapi-gen=true
-type CheckErrorLink struct {
- // URL to a page with more information about the error
- Url string `json:"url"`
- // Human readable error message
- Message string `json:"message"`
+type CheckReport struct {
+ // Number of elements analyzed
+ Count int64 `json:"count"`
+ // List of failures
+ Failures []CheckReportFailure `json:"failures"`
}
-// NewCheckErrorLink creates a new CheckErrorLink object.
-func NewCheckErrorLink() *CheckErrorLink {
- return &CheckErrorLink{}
+// NewCheckReport creates a new CheckReport object.
+func NewCheckReport() *CheckReport {
+ return &CheckReport{
+ Failures: []CheckReportFailure{},
+ }
}
// +k8s:openapi-gen=true
@@ -33,7 +35,22 @@ type CheckReportFailure struct {
// NewCheckReportFailure creates a new CheckReportFailure object.
func NewCheckReportFailure() *CheckReportFailure {
- return &CheckReportFailure{}
+ return &CheckReportFailure{
+ Links: []CheckErrorLink{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type CheckErrorLink struct {
+ // URL to a page with more information about the error
+ Url string `json:"url"`
+ // Human readable error message
+ Message string `json:"message"`
+}
+
+// NewCheckErrorLink creates a new CheckErrorLink object.
+func NewCheckErrorLink() *CheckErrorLink {
+ return &CheckErrorLink{}
}
// +k8s:openapi-gen=true
@@ -56,7 +73,7 @@ func NewCheckstatusOperatorState() *CheckstatusOperatorState {
// +k8s:openapi-gen=true
type CheckStatus struct {
- Report CheckV0alpha1StatusReport `json:"report"`
+ Report CheckReport `json:"report"`
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]CheckstatusOperatorState `json:"operatorStates,omitempty"`
@@ -67,7 +84,7 @@ type CheckStatus struct {
// NewCheckStatus creates a new CheckStatus object.
func NewCheckStatus() *CheckStatus {
return &CheckStatus{
- Report: *NewCheckV0alpha1StatusReport(),
+ Report: *NewCheckReport(),
}
}
@@ -87,16 +104,3 @@ const (
CheckStatusOperatorStateStateInProgress CheckStatusOperatorStateState = "in_progress"
CheckStatusOperatorStateStateFailed CheckStatusOperatorStateState = "failed"
)
-
-// +k8s:openapi-gen=true
-type CheckV0alpha1StatusReport struct {
- // Number of elements analyzed
- Count int64 `json:"count"`
- // List of failures
- Failures []CheckReportFailure `json:"failures"`
-}
-
-// NewCheckV0alpha1StatusReport creates a new CheckV0alpha1StatusReport object.
-func NewCheckV0alpha1StatusReport() *CheckV0alpha1StatusReport {
- return &CheckV0alpha1StatusReport{}
-}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go
index 9998cffb37d..05e019ec5a7 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go
@@ -24,5 +24,8 @@ type CheckTypeMetadata struct {
// NewCheckTypeMetadata creates a new CheckTypeMetadata object.
func NewCheckTypeMetadata() *CheckTypeMetadata {
- return &CheckTypeMetadata{}
+ return &CheckTypeMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go
index 80bd02b1cc8..22d4962c730 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go
@@ -18,8 +18,11 @@ import (
type CheckType struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
- Spec CheckTypeSpec `json:"spec" yaml:"spec"`
- CheckTypeStatus CheckTypeStatus `json:"status" yaml:"status"`
+
+ // Spec is the spec of the CheckType
+ Spec CheckTypeSpec `json:"spec" yaml:"spec"`
+
+ Status CheckTypeStatus `json:"status" yaml:"status"`
}
func (o *CheckType) GetSpec() any {
@@ -37,14 +40,14 @@ func (o *CheckType) SetSpec(spec any) error {
func (o *CheckType) GetSubresources() map[string]any {
return map[string]any{
- "status": o.CheckTypeStatus,
+ "status": o.Status,
}
}
func (o *CheckType) GetSubresource(name string) (any, bool) {
switch name {
case "status":
- return o.CheckTypeStatus, true
+ return o.Status, true
default:
return nil, false
}
@@ -57,7 +60,7 @@ func (o *CheckType) SetSubresource(name string, value any) error {
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type CheckTypeStatus", value)
}
- o.CheckTypeStatus = cast
+ o.Status = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
@@ -219,6 +222,20 @@ func (o *CheckType) DeepCopyObject() runtime.Object {
return o.Copy()
}
+func (o *CheckType) DeepCopy() *CheckType {
+ cpy := &CheckType{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *CheckType) DeepCopyInto(dst *CheckType) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
// Interface compliance compile-time check
var _ resource.Object = &CheckType{}
@@ -262,5 +279,41 @@ func (o *CheckTypeList) SetItems(items []resource.Object) {
}
}
+func (o *CheckTypeList) DeepCopy() *CheckTypeList {
+ cpy := &CheckTypeList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *CheckTypeList) DeepCopyInto(dst *CheckTypeList) {
+ resource.CopyObjectInto(dst, o)
+}
+
// Interface compliance compile-time check
var _ resource.ListObject = &CheckTypeList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *CheckTypeSpec) DeepCopy() *CheckTypeSpec {
+ cpy := &CheckTypeSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *CheckTypeSpec) DeepCopyInto(dst *CheckTypeSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of CheckTypeStatus
+func (s *CheckTypeStatus) DeepCopy() *CheckTypeStatus {
+ cpy := &CheckTypeStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies CheckTypeStatus into another CheckTypeStatus object
+func (s *CheckTypeStatus) DeepCopyInto(dst *CheckTypeStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go
index 528643b69dd..d4d3f2d4f86 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go
@@ -23,5 +23,7 @@ type CheckTypeSpec struct {
// NewCheckTypeSpec creates a new CheckTypeSpec object.
func NewCheckTypeSpec() *CheckTypeSpec {
- return &CheckTypeSpec{}
+ return &CheckTypeSpec{
+ Steps: []CheckTypeStep{},
+ }
}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/constants.go b/apps/advisor/pkg/apis/advisor/v0alpha1/constants.go
index 213249b4c58..80c8a0f0620 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/constants.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/constants.go
@@ -3,16 +3,16 @@ package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema"
const (
- // Group is the API group used by all kinds in this package
- Group = "advisor.grafana.app"
- // Version is the API version used by all kinds in this package
- Version = "v0alpha1"
+ // APIGroup is the API group used by all kinds in this package
+ APIGroup = "advisor.grafana.app"
+ // APIVersion is the API version used by all kinds in this package
+ APIVersion = "v0alpha1"
)
var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{
- Group: Group,
- Version: Version,
+ Group: APIGroup,
+ Version: APIVersion,
}
)
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
index 84e85e7f5ba..21e61de7f45 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
@@ -15,6 +15,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckErrorLink": schema_pkg_apis_advisor_v0alpha1_CheckErrorLink(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReport": schema_pkg_apis_advisor_v0alpha1_CheckReport(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure": schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref),
@@ -24,7 +25,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus": schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep": schema_pkg_apis_advisor_v0alpha1_CheckTypeStep(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref),
}
}
@@ -57,8 +57,9 @@ func schema_pkg_apis_advisor_v0alpha1_Check(ref common.ReferenceCallback) common
},
"spec": {
SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec"),
+ Description: "Spec is the spec of the Check",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec"),
},
},
"status": {
@@ -153,6 +154,43 @@ func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) co
}
}
+func schema_pkg_apis_advisor_v0alpha1_CheckReport(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "count": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Number of elements analyzed",
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "failures": {
+ SchemaProps: spec.SchemaProps{
+ Description: "List of failures",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"count", "failures"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"},
+ }
+}
+
func schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -258,7 +296,7 @@ func schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref common.ReferenceCallback)
"report": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport"),
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReport"),
},
},
"operatorStates": {
@@ -296,7 +334,7 @@ func schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref common.ReferenceCallback)
},
},
Dependencies: []string{
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState"},
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReport", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState"},
}
}
@@ -328,8 +366,9 @@ func schema_pkg_apis_advisor_v0alpha1_CheckType(ref common.ReferenceCallback) co
},
"spec": {
SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec"),
+ Description: "Spec is the spec of the CheckType",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec"),
},
},
"status": {
@@ -566,43 +605,6 @@ func schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref common.Re
}
}
-func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "count": {
- SchemaProps: spec.SchemaProps{
- Description: "Number of elements analyzed",
- Default: 0,
- Type: []string{"integer"},
- Format: "int64",
- },
- },
- "failures": {
- SchemaProps: spec.SchemaProps{
- Description: "List of failures",
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"),
- },
- },
- },
- },
- },
- },
- Required: []string{"count", "failures"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"},
- }
-}
-
func schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
diff --git a/apps/advisor/pkg/apis/advisor_manifest.go b/apps/advisor/pkg/apis/advisor_manifest.go
index 6f5d472dc54..eb596a274e2 100644
--- a/apps/advisor/pkg/apis/advisor_manifest.go
+++ b/apps/advisor/pkg/apis/advisor_manifest.go
@@ -7,15 +7,19 @@ package apis
import (
"encoding/json"
+ "fmt"
"github.com/grafana/grafana-app-sdk/app"
+ "github.com/grafana/grafana-app-sdk/resource"
+
+ v0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
)
var (
- rawSchemaCheckv0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"type":"string"},"description":"Generic data input that a check can receive","type":"object"}},"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"report":{"properties":{"count":{"description":"Number of elements analyzed","type":"integer"},"failures":{"description":"List of failures","items":{"properties":{"item":{"description":"Human readable identifier of the item that failed","type":"string"},"itemID":{"description":"ID of the item that failed","type":"string"},"links":{"description":"Links to actions that can be taken to resolve the failure","items":{"properties":{"message":{"description":"Human readable error message","type":"string"},"url":{"description":"URL to a page with more information about the error","type":"string"}},"required":["url","message"],"type":"object"},"type":"array"},"moreInfo":{"description":"More information about the failure, not meant to be displayed to the user. Used for LLM suggestions.","type":"string"},"severity":{"description":"Severity of the failure","enum":["high","low"],"type":"string"},"stepID":{"description":"Step ID that the failure is associated with","type":"string"}},"required":["severity","stepID","item","itemID","links"],"type":"object"},"type":"array"}},"required":["count","failures"],"type":"object"}},"required":["report"],"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ rawSchemaCheckv0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"type":"string"},"description":"Generic data input that a check can receive","type":"object"}},"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"report":{"properties":{"count":{"description":"Number of elements analyzed","type":"integer"},"failures":{"description":"List of failures","items":{"properties":{"item":{"description":"Human readable identifier of the item that failed","type":"string"},"itemID":{"description":"ID of the item that failed","type":"string"},"links":{"description":"Links to actions that can be taken to resolve the failure","items":{"properties":{"message":{"description":"Human readable error message","type":"string"},"url":{"description":"URL to a page with more information about the error","type":"string"}},"required":["url","message"],"type":"object"},"type":"array"},"moreInfo":{"description":"More information about the failure, not meant to be displayed to the user. Used for LLM suggestions.","type":"string"},"severity":{"description":"Severity of the failure","enum":["high","low"],"type":"string"},"stepID":{"description":"Step ID that the failure is associated with","type":"string"}},"required":["severity","stepID","item","itemID","links"],"type":"object"},"type":"array"}},"required":["count","failures"],"type":"object"}},"required":["report"],"type":"object"}}`)
versionSchemaCheckv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaCheckv0alpha1, &versionSchemaCheckv0alpha1)
- rawSchemaCheckTypev0alpha1 = []byte(`{"spec":{"properties":{"name":{"type":"string"},"steps":{"items":{"properties":{"description":{"type":"string"},"resolution":{"type":"string"},"stepID":{"type":"string"},"title":{"type":"string"}},"required":["title","description","stepID","resolution"],"type":"object"},"type":"array"}},"required":["name","steps"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ rawSchemaCheckTypev0alpha1 = []byte(`{"spec":{"properties":{"name":{"type":"string"},"steps":{"items":{"properties":{"description":{"type":"string"},"resolution":{"type":"string"},"stepID":{"type":"string"},"title":{"type":"string"}},"required":["title","description","stepID","resolution"],"type":"object"},"type":"array"}},"required":["name","steps"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaCheckTypev0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaCheckTypev0alpha1, &versionSchemaCheckTypev0alpha1)
)
@@ -58,12 +62,6 @@ var appManifestData = app.ManifestData{
},
}
-func jsonToMap(j string) map[string]any {
- m := make(map[string]any)
- json.Unmarshal([]byte(j), &j)
- return m
-}
-
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
@@ -71,3 +69,15 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("advisor")
}
+
+var kindVersionToGoType = map[string]resource.Kind{
+ "Check/v0alpha1": v0alpha1.CheckKind(),
+ "CheckType/v0alpha1": v0alpha1.CheckTypeKind(),
+}
+
+// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
+// If there is no association for the provided Kind and Version, exists will return false.
+func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) {
+ goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)]
+ return goType, exists
+}
diff --git a/apps/advisor/pkg/app/checks/utils.go b/apps/advisor/pkg/app/checks/utils.go
index 0abcb8a603b..e58375ee64b 100644
--- a/apps/advisor/pkg/app/checks/utils.go
+++ b/apps/advisor/pkg/app/checks/utils.go
@@ -106,3 +106,25 @@ func SetStatusAnnotation(ctx context.Context, client resource.Client, obj resour
}},
}, resource.PatchOptions{}, obj)
}
+
+func SetAnnotations(ctx context.Context, client resource.Client, obj resource.Object, annotations map[string]string) error {
+ return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
+ Operations: []resource.PatchOperation{{
+ Operation: resource.PatchOpAdd,
+ Path: "/metadata/annotations",
+ Value: annotations,
+ }},
+ }, resource.PatchOptions{}, obj)
+}
+
+func SetStatus(ctx context.Context, client resource.Client, obj resource.Object, status any) error {
+ return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
+ Operations: []resource.PatchOperation{{
+ Operation: resource.PatchOpAdd,
+ Path: "/status",
+ Value: status,
+ }},
+ }, resource.PatchOptions{
+ Subresource: "status",
+ }, obj)
+}
diff --git a/apps/advisor/pkg/app/utils.go b/apps/advisor/pkg/app/utils.go
index 83dba0cf42a..cf090b67260 100644
--- a/apps/advisor/pkg/app/utils.go
+++ b/apps/advisor/pkg/app/utils.go
@@ -78,28 +78,21 @@ func processCheck(ctx context.Context, log logging.Logger, client resource.Clien
return fmt.Errorf("error running steps: %w", err)
}
- report := &advisorv0alpha1.CheckV0alpha1StatusReport{
+ report := &advisorv0alpha1.CheckReport{
Failures: failures,
Count: int64(len(items)),
}
+ c.Status.Report = *report
+ err = checks.SetStatus(ctx, client, obj, c.Status)
+ if err != nil {
+ return err
+ }
// Set the status annotation to processed and annotate the steps ignored
annotations := checks.AddAnnotations(ctx, obj, map[string]string{
checks.StatusAnnotation: checks.StatusAnnotationProcessed,
checks.IgnoreStepsAnnotationList: checkType.GetAnnotations()[checks.IgnoreStepsAnnotationList],
})
- return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
- Operations: []resource.PatchOperation{
- {
- Operation: resource.PatchOpAdd,
- Path: "/status/report",
- Value: *report,
- }, {
- Operation: resource.PatchOpAdd,
- Path: "/metadata/annotations",
- Value: annotations,
- },
- },
- }, resource.PatchOptions{}, obj)
+ return checks.SetAnnotations(ctx, client, obj, annotations)
}
func processCheckRetry(ctx context.Context, log logging.Logger, client resource.Client, typesClient resource.Client, obj resource.Object, check checks.Check) error {
@@ -157,7 +150,7 @@ func processCheckRetry(ctx context.Context, log logging.Logger, client resource.
}
}
// Pull failures from the report for the items to retry
- c.CheckStatus.Report.Failures = slices.DeleteFunc(c.CheckStatus.Report.Failures, func(f advisorv0alpha1.CheckReportFailure) bool {
+ c.Status.Report.Failures = slices.DeleteFunc(c.Status.Report.Failures, func(f advisorv0alpha1.CheckReportFailure) bool {
if f.ItemID == itemToRetry {
for _, newFailure := range failures {
if newFailure.StepID == f.StepID {
@@ -171,19 +164,13 @@ func processCheckRetry(ctx context.Context, log logging.Logger, client resource.
// Failure not in the list of items to retry, keep it
return false
})
+ err = checks.SetStatus(ctx, client, obj, c.Status)
+ if err != nil {
+ return err
+ }
// Delete the retry annotation to mark the check as processed
annotations := checks.DeleteAnnotations(ctx, obj, []string{checks.RetryAnnotation})
- return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
- Operations: []resource.PatchOperation{{
- Operation: resource.PatchOpAdd,
- Path: "/status/report",
- Value: c.CheckStatus.Report,
- }, {
- Operation: resource.PatchOpAdd,
- Path: "/metadata/annotations",
- Value: annotations,
- }},
- }, resource.PatchOptions{}, obj)
+ return checks.SetAnnotations(ctx, client, obj, annotations)
}
func runStepsInParallel(ctx context.Context, log logging.Logger, spec *advisorv0alpha1.CheckSpec, steps []checks.Step, items []any) ([]advisorv0alpha1.CheckReportFailure, error) {
diff --git a/apps/advisor/pkg/app/utils_test.go b/apps/advisor/pkg/app/utils_test.go
index dc8c635f6e8..df4b016db93 100644
--- a/apps/advisor/pkg/app/utils_test.go
+++ b/apps/advisor/pkg/app/utils_test.go
@@ -95,9 +95,9 @@ func TestProcessMultipleCheckItems(t *testing.T) {
err = processCheck(ctx, logging.DefaultLogger, client, typesClient, obj, check)
assert.NoError(t, err)
assert.Equal(t, checks.StatusAnnotationProcessed, obj.GetAnnotations()[checks.StatusAnnotation])
- r := client.lastValue.(advisorv0alpha1.CheckV0alpha1StatusReport)
- assert.Equal(t, r.Count, int64(100))
- assert.Len(t, r.Failures, 50)
+ r := client.values[0].(advisorv0alpha1.CheckStatus)
+ assert.Equal(t, r.Report.Count, int64(100))
+ assert.Len(t, r.Report.Failures, 50)
}
func TestProcessCheck_AlreadyProcessed(t *testing.T) {
@@ -231,7 +231,7 @@ func TestProcessCheckRetry_SkipMissingItem(t *testing.T) {
checks.RetryAnnotation: "item",
checks.StatusAnnotation: checks.StatusAnnotationProcessed,
})
- obj.CheckStatus.Report.Failures = []advisorv0alpha1.CheckReportFailure{
+ obj.Status.Report.Failures = []advisorv0alpha1.CheckReportFailure{
{
ItemID: "item",
StepID: "step",
@@ -254,7 +254,7 @@ func TestProcessCheckRetry_SkipMissingItem(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, checks.StatusAnnotationProcessed, obj.GetAnnotations()[checks.StatusAnnotation])
assert.Empty(t, obj.GetAnnotations()[checks.RetryAnnotation])
- assert.Empty(t, obj.CheckStatus.Report.Failures)
+ assert.Empty(t, obj.Status.Report.Failures)
}
func TestProcessCheckRetry_Success(t *testing.T) {
@@ -263,7 +263,7 @@ func TestProcessCheckRetry_Success(t *testing.T) {
checks.RetryAnnotation: "item",
checks.StatusAnnotation: checks.StatusAnnotationProcessed,
})
- obj.CheckStatus.Report.Failures = []advisorv0alpha1.CheckReportFailure{
+ obj.Status.Report.Failures = []advisorv0alpha1.CheckReportFailure{
{
ItemID: "item",
StepID: "step",
@@ -286,16 +286,16 @@ func TestProcessCheckRetry_Success(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, checks.StatusAnnotationProcessed, obj.GetAnnotations()[checks.StatusAnnotation])
assert.Empty(t, obj.GetAnnotations()[checks.RetryAnnotation])
- assert.Empty(t, obj.CheckStatus.Report.Failures)
+ assert.Empty(t, obj.Status.Report.Failures)
}
type mockClient struct {
resource.Client
- lastValue any
+ values []any
}
func (m *mockClient) PatchInto(ctx context.Context, id resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions, obj resource.Object) error {
- m.lastValue = req.Operations[0].Value
+ m.values = append(m.values, req.Operations[0].Value)
return nil
}
diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod
index 21243f3510a..f9ea5babd51 100644
--- a/apps/alerting/notifications/go.mod
+++ b/apps/alerting/notifications/go.mod
@@ -3,10 +3,10 @@ module github.com/grafana/grafana/apps/alerting/notifications
go 1.24.4
require (
- github.com/grafana/grafana-app-sdk v0.39.0
- github.com/grafana/grafana-app-sdk/logging v0.38.2
- k8s.io/apimachinery v0.33.1
- k8s.io/apiserver v0.33.1
+ github.com/grafana/grafana-app-sdk v0.39.2
+ github.com/grafana/grafana-app-sdk/logging v0.39.1
+ k8s.io/apimachinery v0.33.2
+ k8s.io/apiserver v0.33.2
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -89,18 +89,18 @@ require (
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.11.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
- google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
+ google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.33.1 // indirect
- k8s.io/apiextensions-apiserver v0.33.1 // indirect
- k8s.io/client-go v0.33.1 // indirect
- k8s.io/component-base v0.33.1 // indirect
+ k8s.io/api v0.33.2 // indirect
+ k8s.io/apiextensions-apiserver v0.33.2 // indirect
+ k8s.io/client-go v0.33.2 // indirect
+ k8s.io/component-base v0.33.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum
index 1ce129e856f..c906b01a1af 100644
--- a/apps/alerting/notifications/go.sum
+++ b/apps/alerting/notifications/go.sum
@@ -84,10 +84,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
-github.com/grafana/grafana-app-sdk v0.39.0 h1:WC2E9BKXWDX/e2bajdAFjQEyyWf9BFp7Yzbjm6T1T1w=
-github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
-github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
-github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
@@ -317,12 +317,12 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
-google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
+google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
@@ -352,18 +352,18 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
-k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
-k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
-k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
-k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
-k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/apiserver v0.33.1 h1:yLgLUPDVC6tHbNcw5uE9mo1T6ELhJj7B0geifra3Qdo=
-k8s.io/apiserver v0.33.1/go.mod h1:VMbE4ArWYLO01omz+k8hFjAdYfc3GVAYPrhP2tTKccs=
-k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
-k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
-k8s.io/component-base v0.33.1 h1:EoJ0xA+wr77T+G8p6T3l4efT2oNwbqBVKR71E0tBIaI=
-k8s.io/component-base v0.33.1/go.mod h1:guT/w/6piyPfTgq7gfvgetyXMIh10zuXA6cRRm3rDuY=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8=
+k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/apiserver v0.33.2 h1:KGTRbxn2wJagJowo29kKBp4TchpO1DRO3g+dB/KOJN4=
+k8s.io/apiserver v0.33.2/go.mod h1:9qday04wEAMLPWWo9AwqCZSiIn3OYSZacDyu/AcoM/M=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
+k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0=
+k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_schema_gen.go b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_schema_gen.go
index acda5c7d1c9..314d36b602a 100644
--- a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_schema_gen.go
+++ b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_schema_gen.go
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
- resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
+ resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*Receiver)
diff --git a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/templategroup_schema_gen.go b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/templategroup_schema_gen.go
index 339d0bd6d04..509bfc4aeca 100644
--- a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/templategroup_schema_gen.go
+++ b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/templategroup_schema_gen.go
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
- resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
+ resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TemplateGroup)
diff --git a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_schema_gen.go b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_schema_gen.go
index a6c809e0d3b..8c5459f0059 100644
--- a/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_schema_gen.go
+++ b/apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_schema_gen.go
@@ -13,7 +13,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
- resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{resource.SelectableField{
+ resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.name",
FieldValueFunc: func(o resource.Object) (string, error) {
cast, ok := o.(*TimeInterval)
diff --git a/apps/dashboard/Makefile b/apps/dashboard/Makefile
index 1a948f1b9a8..950c809c0ec 100644
--- a/apps/dashboard/Makefile
+++ b/apps/dashboard/Makefile
@@ -1,4 +1,4 @@
-APP_SDK_VERSION := v0.39.0
+APP_SDK_VERSION := v0.39.2
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk
@@ -60,3 +60,10 @@ post-generate-cleanup: ## Clean up the generated code
@echo "// To sync changes, run: make generate in apps/dashboard" >> ./pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
@echo "" >> ./pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
@cat ./kinds/v2alpha1/dashboard_spec.cue >> ./pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
+
+ # Copy dashboard/v2alpha2 spec so we can use it for schema validation
+ @echo "// This file is managed by grafana-app-sdk - DO NOT EDIT MANUALLY" > ./pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
+ @echo "// Source: apps/dashboard/kinds/v2alpha2/dashboard_spec.cue" >> ./pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
+ @echo "// To sync changes, run: make generate in apps/dashboard" >> ./pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
+ @echo "" >> ./pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
+ @cat ./kinds/v2alpha2/dashboard_spec.cue >> ./pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
diff --git a/apps/dashboard/go.mod b/apps/dashboard/go.mod
index 6d9028dccf9..837887e08e1 100644
--- a/apps/dashboard/go.mod
+++ b/apps/dashboard/go.mod
@@ -4,11 +4,11 @@ go 1.24.4
require (
cuelang.org/go v0.11.1
- github.com/grafana/grafana-app-sdk v0.39.0
+ github.com/grafana/grafana-app-sdk v0.39.2
github.com/grafana/grafana-plugin-sdk-go v0.278.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
github.com/stretchr/testify v1.10.0
- k8s.io/apimachinery v0.33.1
+ k8s.io/apimachinery v0.33.2
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -44,7 +44,7 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
github.com/grafana/otel-profiling-go v0.5.1 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
@@ -116,14 +116,14 @@ require (
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.34.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/client-go v0.33.1 // indirect
+ k8s.io/client-go v0.33.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
diff --git a/apps/dashboard/go.sum b/apps/dashboard/go.sum
index 412e87a6034..b73b3aab637 100644
--- a/apps/dashboard/go.sum
+++ b/apps/dashboard/go.sum
@@ -94,10 +94,10 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
-github.com/grafana/grafana-app-sdk v0.39.0 h1:WC2E9BKXWDX/e2bajdAFjQEyyWf9BFp7Yzbjm6T1T1w=
-github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
-github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
-github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana-plugin-sdk-go v0.278.0 h1:5/rIYparLi02pofdaag8wnjspMMVNCi8cZhC4cdC3Ho=
github.com/grafana/grafana-plugin-sdk-go v0.278.0/go.mod h1:+8NXT/XUJ/89GV6FxGQ366NZ3nU+cAXDMd0OUESF9H4=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
@@ -357,10 +357,10 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
@@ -379,12 +379,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
-k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
-k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
-k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
-k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/apps/dashboard/kinds/dashboard.cue b/apps/dashboard/kinds/dashboard.cue
index b8aaf17bc7c..d48765539c8 100644
--- a/apps/dashboard/kinds/dashboard.cue
+++ b/apps/dashboard/kinds/dashboard.cue
@@ -3,7 +3,8 @@ package kinds
import (
v0 "github.com/grafana/grafana/sdkkinds/dashboard/v0alpha1"
v1 "github.com/grafana/grafana/sdkkinds/dashboard/v1beta1"
- v2 "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha1"
+ v2alpha1 "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha1"
+ v2alpha2 "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha2"
)
// Status is the shared status of all dashboard versions.
@@ -63,7 +64,13 @@ dashboard: {
}
"v2alpha1": {
schema: {
- spec: v2.DashboardSpec
+ spec: v2alpha1.DashboardSpec
+ status: DashboardStatus
+ }
+ }
+ "v2alpha2": {
+ schema: {
+ spec: v2alpha2.DashboardSpec
status: DashboardStatus
}
}
diff --git a/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
index ccce02984c8..8ab1891e626 100644
--- a/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
+++ b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
@@ -734,6 +734,8 @@ QueryVariableSpec: {
allValue?: string
placeholder?: string
allowCustomValue: bool | *true
+ staticOptions?: [...VariableOption]
+ staticOptionsOrder?: "before" | "after" | "sorted"
}
// Query variable kind
diff --git a/apps/dashboard/kinds/v2alpha2/dashboard_spec.cue b/apps/dashboard/kinds/v2alpha2/dashboard_spec.cue
new file mode 100644
index 00000000000..4c1202caea7
--- /dev/null
+++ b/apps/dashboard/kinds/v2alpha2/dashboard_spec.cue
@@ -0,0 +1,964 @@
+package v2alpha2
+
+DashboardSpec: {
+ annotations: [...AnnotationQueryKind] | *[]
+
+ // Configuration of dashboard cursor sync behavior.
+ // "Off" for no shared crosshair or tooltip (default).
+ // "Crosshair" for shared crosshair.
+ // "Tooltip" for shared crosshair AND shared tooltip.
+ cursorSync: DashboardCursorSync
+
+ // Description of dashboard.
+ description?: string
+
+ // Whether a dashboard is editable or not.
+ editable?: bool | *true
+
+ elements: [ElementReference.name]: Element | *{}
+
+ layout: GridLayoutKind | RowsLayoutKind | AutoGridLayoutKind | TabsLayoutKind
+
+ // Links with references to other dashboards or external websites.
+ links: [...DashboardLink] | *[]
+
+ // When set to true, the dashboard will redraw panels at an interval matching the pixel width.
+ // This will keep data "moving left" regardless of the query refresh rate. This setting helps
+ // avoid dashboards presenting stale live data.
+ liveNow?: bool
+
+ // When set to true, the dashboard will load all panels in the dashboard when it's loaded.
+ preload: bool | *false
+
+ // Plugins only. The version of the dashboard installed together with the plugin.
+ // This is used to determine if the dashboard should be updated when the plugin is updated.
+ revision?: uint16
+
+ // Tags associated with dashboard.
+ tags: [...string] | *[]
+
+ timeSettings: TimeSettingsSpec
+
+ // Title of dashboard.
+ title: string
+
+ // Configured template variables.
+ variables: [...VariableKind] | *[]
+}
+
+// Supported dashboard elements
+Element: PanelKind | LibraryPanelKind // |* more element types in the future
+
+LibraryPanelKind: {
+ kind: "LibraryPanel"
+ spec: LibraryPanelKindSpec
+}
+
+LibraryPanelKindSpec: {
+ // Panel ID for the library panel in the dashboard
+ id: number
+ // Title for the library panel in the dashboard
+ title: string
+
+ libraryPanel: LibraryPanelRef
+}
+
+// A library panel is a reusable panel that you can use in any dashboard.
+// When you make a change to a library panel, that change propagates to all instances of where the panel is used.
+// Library panels streamline reuse of panels across multiple dashboards.
+LibraryPanelRef: {
+ // Library panel name
+ name: string
+ // Library panel uid
+ uid: string
+}
+
+AnnotationPanelFilter: {
+ // Should the specified panels be included or excluded
+ exclude?: bool | *false
+
+ // Panel IDs that should be included or excluded
+ ids: [...uint32]
+}
+
+// "Off" for no shared crosshair or tooltip (default).
+// "Crosshair" for shared crosshair.
+// "Tooltip" for shared crosshair AND shared tooltip.
+DashboardCursorSync: "Crosshair" | "Tooltip" | *"Off"
+
+// Links with references to other dashboards or external resources
+DashboardLink: {
+ // Title to display with the link
+ title: string
+ // Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+ // FIXME: The type is generated as `type: DashboardLinkType | dashboardLinkType.Link;` but it should be `type: DashboardLinkType`
+ type: DashboardLinkType
+ // Icon name to be displayed with the link
+ icon: string
+ // Tooltip to display when the user hovers their mouse over it
+ tooltip: string
+ // Link URL. Only required/valid if the type is link
+ url?: string
+ // List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards
+ tags: [...string] | *[]
+ // If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards
+ asDropdown: bool | *false
+ // If true, the link will be opened in a new tab
+ targetBlank: bool | *false
+ // If true, includes current template variables values in the link as query params
+ includeVars: bool | *false
+ // If true, includes current time range in the link as query params
+ keepTime: bool | *false
+}
+
+DataSourceRef: {
+ // The plugin type-id
+ type?: string
+
+ // Specific datasource instance
+ uid?: string
+}
+
+// A topic is attached to DataFrame metadata in query results.
+// This specifies where the data should be used.
+DataTopic: "series" | "annotations" | "alertStates" @cog(kind="enum",memberNames="Series|Annotations|AlertStates")
+
+// Transformations allow to manipulate data returned by a query before the system applies a visualization.
+// Using transformations you can: rename fields, join time series data, perform mathematical operations across queries,
+// use the output of one transformation as the input to another transformation, etc.
+DataTransformerConfig: {
+ // Unique identifier of transformer
+ id: string
+ // Disabled transformations are skipped
+ disabled?: bool
+ // Optional frame matcher. When missing it will be applied to all results
+ filter?: MatcherConfig
+ // Where to pull DataFrames from as input to transformation
+ topic?: DataTopic
+ // Options to be passed to the transformer
+ // Valid options depend on the transformer id
+ options: _
+}
+
+DataLink: {
+ title: string
+ url: string
+ targetBlank?: bool
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+FieldConfigSource: {
+ // Defaults are the options applied to all fields.
+ defaults: FieldConfig
+ // Overrides are the options applied to specific fields overriding the defaults.
+ overrides: [...{
+ matcher: MatcherConfig
+ properties: [...DynamicConfigValue]
+ }]
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+FieldConfig: {
+ // The display value for this field. This supports template variables blank is auto
+ displayName?: string
+
+ // This can be used by data sources that return and explicit naming structure for values and labels
+ // When this property is configured, this value is used rather than the default naming strategy.
+ displayNameFromDS?: string
+
+ // Human readable field metadata
+ description?: string
+
+ // An explicit path to the field in the datasource. When the frame meta includes a path,
+ // This will default to `${frame.meta.path}/${field.name}
+ //
+ // When defined, this value can be used as an identifier within the datasource scope, and
+ // may be used to update the results
+ path?: string
+
+ // True if data source can write a value to the path. Auth/authz are supported separately
+ writeable?: bool
+
+ // True if data source field supports ad-hoc filters
+ filterable?: bool
+
+ // Unit a field should use. The unit you select is applied to all fields except time.
+ // You can use the units ID availables in Grafana or a custom unit.
+ // Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts
+ // As custom unit, you can use the following formats:
+ // `suffix:` for custom unit that should go after value.
+ // `prefix:` for custom unit that should go before value.
+ // `time:` For custom date time formats type for example `time:YYYY-MM-DD`.
+ // `si:` for custom SI units. For example: `si: mF`. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.
+ // `count:` for a custom count unit.
+ // `currency:` for custom a currency unit.
+ unit?: string
+
+ // Specify the number of decimals Grafana includes in the rendered value.
+ // If you leave this field blank, Grafana automatically truncates the number of decimals based on the value.
+ // For example 1.1234 will display as 1.12 and 100.456 will display as 100.
+ // To display all decimals, set the unit to `String`.
+ decimals?: number
+
+ // The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ min?: number
+ // The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ max?: number
+
+ // Convert input values into a display string
+ mappings?: [...ValueMapping]
+
+ // Map numeric values to states
+ thresholds?: ThresholdsConfig
+
+ // Panel color configuration
+ color?: FieldColor
+
+ // The behavior when clicking on a result
+ links?: [...]
+
+ // Alternative to empty string
+ noValue?: string
+
+ // custom is specified by the FieldConfig field
+ // in panel plugin schemas.
+ custom?: {...}
+}
+
+DynamicConfigValue: {
+ id: string | *""
+ value?: _
+}
+
+// Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.
+// It comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.
+MatcherConfig: {
+ // The matcher id. This is used to find the matcher implementation from registry.
+ id: string | *""
+ // The matcher options. This is specific to the matcher implementation.
+ options?: _
+}
+
+Threshold: {
+ value: number
+ color: string
+}
+
+ThresholdsMode: "absolute" | "percentage"
+
+ThresholdsConfig: {
+ mode: ThresholdsMode
+ steps: [...Threshold]
+}
+
+ValueMapping: ValueMap | RangeMap | RegexMap | SpecialValueMap
+
+// Supported value mapping types
+// `value`: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+// `range`: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+// `regex`: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+// `special`: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.
+MappingType: "value" | "range" | "regex" | "special"
+
+// Maps text values to a color or different display text and color.
+// For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+ValueMap: {
+ type: MappingType & "value"
+ // Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } }
+ options: [string]: ValueMappingResult
+}
+
+// Maps numerical ranges to a display text and color.
+// For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+RangeMap: {
+ type: MappingType & "range"
+ // Range to match against and the result to apply when the value is within the range
+ options: {
+ // Min value of the range. It can be null which means -Infinity
+ from: float64 | null
+ // Max value of the range. It can be null which means +Infinity
+ to: float64 | null
+ // Config to apply when the value is within the range
+ result: ValueMappingResult
+ }
+}
+
+// Maps regular expressions to replacement text and a color.
+// For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+RegexMap: {
+ type: MappingType & "regex"
+ // Regular expression to match against and the result to apply when the value matches the regex
+ options: {
+ // Regular expression to match against
+ pattern: string
+ // Config to apply when the value matches the regex
+ result: ValueMappingResult
+ }
+}
+
+// Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.
+// See SpecialValueMatch to see the list of special values.
+// For example, you can configure a special value mapping so that null values appear as N/A.
+SpecialValueMap: {
+ type: MappingType & "special"
+ options: {
+ // Special value to match against
+ match: SpecialValueMatch
+ // Config to apply when the value matches the special value
+ result: ValueMappingResult
+ }
+}
+
+// Special value types supported by the `SpecialValueMap`
+SpecialValueMatch: "true" | "false" | "null" | "nan" | "null+nan" | "empty" @cog(kind="enum",memberNames="True|False|Null|NaN|NullAndNaN|Empty")
+
+// Result used as replacement with text and color when the value matches
+ValueMappingResult: {
+ // Text to display when the value matches
+ text?: string
+ // Text to use when the value matches
+ color?: string
+ // Icon to display when the value matches. Only specific visualizations.
+ icon?: string
+ // Position in the mapping array. Only used internally.
+ index?: int32
+}
+
+// Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
+// Continuous color interpolates a color using the percentage of a value relative to min and max.
+// Accepted values are:
+// `thresholds`: From thresholds. Informs Grafana to take the color from the matching threshold
+// `palette-classic`: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations
+// `palette-classic-by-name`: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations
+// `continuous-GrYlRd`: ontinuous Green-Yellow-Red palette mode
+// `continuous-RdYlGr`: Continuous Red-Yellow-Green palette mode
+// `continuous-BlYlRd`: Continuous Blue-Yellow-Red palette mode
+// `continuous-YlRd`: Continuous Yellow-Red palette mode
+// `continuous-BlPu`: Continuous Blue-Purple palette mode
+// `continuous-YlBl`: Continuous Yellow-Blue palette mode
+// `continuous-blues`: Continuous Blue palette mode
+// `continuous-reds`: Continuous Red palette mode
+// `continuous-greens`: Continuous Green palette mode
+// `continuous-purples`: Continuous Purple palette mode
+// `shades`: Shades of a single color. Specify a single color, useful in an override rule.
+// `fixed`: Fixed color mode. Specify a single color, useful in an override rule.
+FieldColorModeId: "thresholds" | "palette-classic" | "palette-classic-by-name" | "continuous-GrYlRd" | "continuous-RdYlGr" | "continuous-BlYlRd" | "continuous-YlRd" | "continuous-BlPu" | "continuous-YlBl" | "continuous-blues" | "continuous-reds" | "continuous-greens" | "continuous-purples" | "fixed" | "shades"
+
+// Defines how to assign a series color from "by value" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.
+FieldColorSeriesByMode: "min" | "max" | "last"
+
+// Map a field to a color.
+FieldColor: {
+ // The main color scheme mode.
+ mode: FieldColorModeId
+ // The fixed color value for fixed or shades color modes.
+ fixedColor?: string
+ // Some visualizations need to know how to assign a series color from by value color schemes.
+ seriesBy?: FieldColorSeriesByMode
+}
+
+// Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+DashboardLinkType: "link" | "dashboards"
+
+// --- Common types ---
+Kind: {
+ kind: string
+ spec: _
+ metadata?: _
+}
+
+// --- Kinds ---
+VizConfigSpec: {
+ pluginVersion: string
+ options: [string]: _
+ fieldConfig: FieldConfigSource
+}
+
+VizConfigKind: {
+ // The kind of a VizConfigKind is the plugin ID
+ kind: string
+ spec: VizConfigSpec
+}
+
+AnnotationQuerySpec: {
+ datasource?: DataSourceRef
+ query?: DataQueryKind
+ enable: bool
+ hide: bool
+ iconColor: string
+ name: string
+ builtIn?: bool | *false
+ filter?: AnnotationPanelFilter
+ legacyOptions?: [string]: _ //Catch-all field for datasource-specific properties
+}
+
+AnnotationQueryKind: {
+ kind: "AnnotationQuery"
+ spec: AnnotationQuerySpec
+}
+
+QueryOptionsSpec: {
+ timeFrom?: string
+ maxDataPoints?: int
+ timeShift?: string
+ queryCachingTTL?: int
+ interval?: string
+ cacheTimeout?: string
+ hideTimeOverride?: bool
+}
+
+DataQueryKind: {
+ // The kind of a DataQueryKind is the datasource type
+ kind: string
+ spec: [string]: _
+}
+
+PanelQuerySpec: {
+ query: DataQueryKind
+ datasource?: DataSourceRef
+
+ refId: string
+ hidden: bool
+}
+
+PanelQueryKind: {
+ kind: "PanelQuery"
+ spec: PanelQuerySpec
+}
+
+TransformationKind: {
+ // The kind of a TransformationKind is the transformation ID
+ kind: string
+ spec: DataTransformerConfig
+}
+
+QueryGroupSpec: {
+ queries: [...PanelQueryKind]
+ transformations: [...TransformationKind]
+ queryOptions: QueryOptionsSpec
+}
+
+QueryGroupKind: {
+ kind: "QueryGroup"
+ spec: QueryGroupSpec
+}
+
+TimeRangeOption: {
+ display: string | *"Last 6 hours"
+ from: string | *"now-6h"
+ to: string | *"now"
+}
+
+// Time configuration
+// It defines the default time config for the time picker, the refresh picker for the specific dashboard.
+TimeSettingsSpec: {
+ // Timezone of dashboard. Accepted values are IANA TZDB zone ID or "browser" or "utc".
+ timezone?: string | *"browser"
+ // Start time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ from: string | *"now-6h"
+ // End time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ to: string | *"now"
+ // Refresh rate of dashboard. Represented via interval string, e.g. "5s", "1m", "1h", "1d".
+ autoRefresh: string | *"" // v1: refresh
+ // Interval options available in the refresh picker dropdown.
+ autoRefreshIntervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] // v1: timepicker.refresh_intervals
+ // Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
+ quickRanges?: [...TimeRangeOption] // v1: timepicker.quick_ranges , not exposed in the UI
+ // Whether timepicker is visible or not.
+ hideTimepicker: bool | *false // v1: timepicker.hidden
+ // Day when the week starts. Expressed by the name of the day in lowercase, e.g. "monday".
+ weekStart?: "saturday" | "monday" | "sunday"
+ // The month that the fiscal year starts on. 0 = January, 11 = December
+ fiscalYearStartMonth: int | *0
+ // Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
+ nowDelay?: string // v1: timepicker.nowDelay
+}
+
+RepeatMode: "variable" // other repeat modes will be added in the future: label, frame
+
+RepeatOptions: {
+ mode: RepeatMode
+ value: string
+ direction?: "h" | "v"
+ maxPerRow?: int
+}
+
+RowRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+TabRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+AutoGridRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+GridLayoutItemSpec: {
+ x: int
+ y: int
+ width: int
+ height: int
+ element: ElementReference // reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference
+ repeat?: RepeatOptions
+}
+
+GridLayoutItemKind: {
+ kind: "GridLayoutItem"
+ spec: GridLayoutItemSpec
+}
+
+GridLayoutSpec: {
+ items: [...GridLayoutItemKind]
+}
+
+GridLayoutKind: {
+ kind: "GridLayout"
+ spec: GridLayoutSpec
+}
+
+RowsLayoutKind: {
+ kind: "RowsLayout"
+ spec: RowsLayoutSpec
+}
+
+RowsLayoutSpec: {
+ rows: [...RowsLayoutRowKind]
+}
+
+RowsLayoutRowKind: {
+ kind: "RowsLayoutRow"
+ spec: RowsLayoutRowSpec
+}
+
+RowsLayoutRowSpec: {
+ title?: string
+ collapse?: bool
+ hideHeader?: bool
+ fillScreen?: bool
+ conditionalRendering?: ConditionalRenderingGroupKind
+ repeat?: RowRepeatOptions
+ layout: GridLayoutKind | AutoGridLayoutKind | TabsLayoutKind | RowsLayoutKind
+}
+
+AutoGridLayoutKind: {
+ kind: "AutoGridLayout"
+ spec: AutoGridLayoutSpec
+}
+
+AutoGridLayoutSpec: {
+ maxColumnCount?: number | *3
+ columnWidthMode: "narrow" | *"standard" | "wide" | "custom"
+ columnWidth?: number
+ rowHeightMode: "short" | *"standard" | "tall" | "custom"
+ rowHeight?: number
+ fillScreen?: bool | *false
+ items: [...AutoGridLayoutItemKind]
+}
+
+AutoGridLayoutItemKind: {
+ kind: "AutoGridLayoutItem"
+ spec: AutoGridLayoutItemSpec
+}
+
+AutoGridLayoutItemSpec: {
+ element: ElementReference
+ repeat?: AutoGridRepeatOptions
+ conditionalRendering?: ConditionalRenderingGroupKind
+}
+
+TabsLayoutKind: {
+ kind: "TabsLayout"
+ spec: TabsLayoutSpec
+}
+
+TabsLayoutSpec: {
+ tabs: [...TabsLayoutTabKind]
+}
+
+TabsLayoutTabKind: {
+ kind: "TabsLayoutTab"
+ spec: TabsLayoutTabSpec
+}
+
+TabsLayoutTabSpec: {
+ title?: string
+ layout: GridLayoutKind | RowsLayoutKind | AutoGridLayoutKind | TabsLayoutKind
+ conditionalRendering?: ConditionalRenderingGroupKind
+ repeat?: TabRepeatOptions
+}
+
+PanelSpec: {
+ id: number
+ title: string
+ description: string
+ links: [...DataLink]
+ data: QueryGroupKind
+ vizConfig: VizConfigKind
+ transparent?: bool
+}
+
+PanelKind: {
+ kind: "Panel"
+ spec: PanelSpec
+}
+
+ElementReference: {
+ kind: "ElementReference"
+ name: string
+}
+
+// Start FIXME: variables - in CUE PR - this are things that should be added into the cue schema
+// TODO: properties such as `hide`, `skipUrlSync`, `multi` are type boolean, and in the old schema they are conditional,
+// should we make them conditional in the new schema as well? or should we make them required but default to false?
+
+// Variable types
+VariableValue: VariableValueSingle | [...VariableValueSingle]
+
+VariableValueSingle: string | bool | number | CustomVariableValue
+
+// Custom formatter variable
+CustomFormatterVariable: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+}
+
+// Custom variable value
+CustomVariableValue: {
+ // The format name or function used in the expression
+ formatter: *null | string | VariableCustomFormatterFn
+}
+
+// Custom formatter function
+VariableCustomFormatterFn: {
+ value: _
+ legacyVariableModel: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+ }
+ legacyDefaultFormatter?: VariableCustomFormatterFn
+}
+
+// Dashboard variable type
+// `query`: Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on.
+// `adhoc`: Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only).
+// `constant`: Define a hidden constant.
+// `datasource`: Quickly change the data source for an entire dashboard.
+// `interval`: Interval variables represent time spans.
+// `textbox`: Display a free text input field with an optional default value.
+// `custom`: Define the variable options manually using a comma-separated list.
+// `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
+VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" |
+ "system" | "snapshot"
+
+VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind
+
+// Sort variable options
+// Accepted values are:
+// `disabled`: No sorting
+// `alphabeticalAsc`: Alphabetical ASC
+// `alphabeticalDesc`: Alphabetical DESC
+// `numericalAsc`: Numerical ASC
+// `numericalDesc`: Numerical DESC
+// `alphabeticalCaseInsensitiveAsc`: Alphabetical Case Insensitive ASC
+// `alphabeticalCaseInsensitiveDesc`: Alphabetical Case Insensitive DESC
+// `naturalAsc`: Natural ASC
+// `naturalDesc`: Natural DESC
+// VariableSort enum with default value
+VariableSort: "disabled" | "alphabeticalAsc" | "alphabeticalDesc" | "numericalAsc" | "numericalDesc" | "alphabeticalCaseInsensitiveAsc" | "alphabeticalCaseInsensitiveDesc" | "naturalAsc" | "naturalDesc"
+
+// Options to config when to refresh a variable
+// `never`: Never refresh the variable
+// `onDashboardLoad`: Queries the data source every time the dashboard loads.
+// `onTimeRangeChanged`: Queries the data source when the dashboard time range changes.
+VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
+
+// Determine if the variable shows on dashboard
+// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
+VariableHide: *"dontHide" | "hideLabel" | "hideVariable"
+
+// Determine the origin of the adhoc variable filter
+FilterOrigin: "dashboard"
+
+// FIXME: should we introduce this? --- Variable value option
+VariableValueOption: {
+ label: string
+ value: VariableValueSingle
+ group?: string
+}
+
+// Variable option specification
+VariableOption: {
+ // Whether the option is selected or not
+ selected?: bool
+ // Text to be displayed for the option
+ text: string | [...string]
+ // Value of the option
+ value: string | [...string]
+}
+
+// Query variable specification
+QueryVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ refresh: VariableRefresh
+ skipUrlSync: bool | *false
+ description?: string
+ datasource?: DataSourceRef
+ query: DataQueryKind
+ regex: string | *""
+ sort: VariableSort
+ definition?: string
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ placeholder?: string
+ allowCustomValue: bool | *true
+ staticOptions?: [...VariableOption]
+ staticOptionsOrder?: "before" | "after" | "sorted"
+}
+
+// Query variable kind
+QueryVariableKind: {
+ kind: "QueryVariable"
+ spec: QueryVariableSpec
+}
+
+// Text variable specification
+TextVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ query: string | *""
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Text variable kind
+TextVariableKind: {
+ kind: "TextVariable"
+ spec: TextVariableSpec
+}
+
+// Constant variable specification
+ConstantVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Constant variable kind
+ConstantVariableKind: {
+ kind: "ConstantVariable"
+ spec: ConstantVariableSpec
+}
+
+// Datasource variable specification
+DatasourceVariableSpec: {
+ name: string | *""
+ pluginId: string | *""
+ refresh: VariableRefresh
+ regex: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Datasource variable kind
+DatasourceVariableKind: {
+ kind: "DatasourceVariable"
+ spec: DatasourceVariableSpec
+}
+
+// Interval variable specification
+IntervalVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ auto: bool | *false
+ auto_min: string | *""
+ auto_count: int | *0
+ refresh: VariableRefresh
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Interval variable kind
+IntervalVariableKind: {
+ kind: "IntervalVariable"
+ spec: IntervalVariableSpec
+}
+
+// Custom variable specification
+CustomVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Custom variable kind
+CustomVariableKind: {
+ kind: "CustomVariable"
+ spec: CustomVariableSpec
+}
+
+// GroupBy variable specification
+GroupByVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ defaultValue?: VariableOption
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Group variable kind
+GroupByVariableKind: {
+ kind: "GroupByVariable"
+ spec: GroupByVariableSpec
+}
+
+// Adhoc variable specification
+AdhocVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ baseFilters: [...AdHocFilterWithLabels] | *[]
+ filters: [...AdHocFilterWithLabels] | *[]
+ defaultKeys: [...MetricFindValue] | *[]
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Define the MetricFindValue type
+MetricFindValue: {
+ text: string
+ value?: string | number
+ group?: string
+ expandable?: bool
+}
+
+// Define the AdHocFilterWithLabels type
+AdHocFilterWithLabels: {
+ key: string
+ operator: string
+ value: string
+ values?: [...string]
+ keyLabel?: string
+ valueLabels?: [...string]
+ forceEdit?: bool
+ origin?: FilterOrigin
+ // @deprecated
+ condition?: string
+}
+
+// Adhoc variable kind
+AdhocVariableKind: {
+ kind: "AdhocVariable"
+ spec: AdhocVariableSpec
+}
+
+ConditionalRenderingGroupKind: {
+ kind: "ConditionalRenderingGroup"
+ spec: ConditionalRenderingGroupSpec
+}
+
+ConditionalRenderingGroupSpec: {
+ visibility: "show" | "hide"
+ condition: "and" | "or"
+ items: [...ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeRangeSizeKind]
+}
+
+ConditionalRenderingVariableKind: {
+ kind: "ConditionalRenderingVariable"
+ spec: ConditionalRenderingVariableSpec
+}
+
+ConditionalRenderingVariableSpec: {
+ variable: string
+ operator: "equals" | "notEquals"
+ value: string
+}
+
+ConditionalRenderingDataKind: {
+ kind: "ConditionalRenderingData"
+ spec: ConditionalRenderingDataSpec
+}
+
+ConditionalRenderingDataSpec: {
+ value: bool
+}
+
+ConditionalRenderingTimeRangeSizeKind: {
+ kind: "ConditionalRenderingTimeRangeSize"
+ spec: ConditionalRenderingTimeRangeSizeSpec
+}
+
+ConditionalRenderingTimeRangeSizeSpec: {
+ value: string
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue
index b9fd38146b7..de90006e396 100644
--- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue
+++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue
@@ -219,6 +219,10 @@ lineage: schemas: [{
// Optional field, if you want to extract part of a series name or metric node segment.
// Named capture groups can be used to separate the display text and value.
regex?: string
+ // Additional static options for query variable
+ staticOptions?: [...#VariableOption]
+ // Ordering of static options in relation to options returned from data source for query variable
+ staticOptionsOrder?: "before" | "after" | "sorted"
...
} @cuetsy(kind="interface") @grafana(TSVeneer="type") @grafanamaturity(NeedsExpertReview)
diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue
index b9fd38146b7..de90006e396 100644
--- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue
+++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue
@@ -219,6 +219,10 @@ lineage: schemas: [{
// Optional field, if you want to extract part of a series name or metric node segment.
// Named capture groups can be used to separate the display text and value.
regex?: string
+ // Additional static options for query variable
+ staticOptions?: [...#VariableOption]
+ // Ordering of static options in relation to options returned from data source for query variable
+ staticOptionsOrder?: "before" | "after" | "sorted"
...
} @cuetsy(kind="interface") @grafana(TSVeneer="type") @grafanamaturity(NeedsExpertReview)
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
index 98fc8804de6..160adf4e7bf 100644
--- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
@@ -738,6 +738,8 @@ QueryVariableSpec: {
allValue?: string
placeholder?: string
allowCustomValue: bool | *true
+ staticOptions?: [...VariableOption]
+ staticOptionsOrder?: "before" | "after" | "sorted"
}
// Query variable kind
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go
index 5b599cb414e..9ddbe89502f 100644
--- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go
@@ -763,7 +763,9 @@ type DashboardRepeatOptions struct {
// NewDashboardRepeatOptions creates a new DashboardRepeatOptions object.
func NewDashboardRepeatOptions() *DashboardRepeatOptions {
- return &DashboardRepeatOptions{}
+ return &DashboardRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
}
// other repeat modes will be added in the future: label, frame
@@ -938,7 +940,9 @@ type DashboardRowRepeatOptions struct {
// NewDashboardRowRepeatOptions creates a new DashboardRowRepeatOptions object.
func NewDashboardRowRepeatOptions() *DashboardRowRepeatOptions {
- return &DashboardRowRepeatOptions{}
+ return &DashboardRowRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
}
// +k8s:openapi-gen=true
@@ -1011,7 +1015,9 @@ type DashboardAutoGridRepeatOptions struct {
// NewDashboardAutoGridRepeatOptions creates a new DashboardAutoGridRepeatOptions object.
func NewDashboardAutoGridRepeatOptions() *DashboardAutoGridRepeatOptions {
- return &DashboardAutoGridRepeatOptions{}
+ return &DashboardAutoGridRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
}
// +k8s:openapi-gen=true
@@ -1077,7 +1083,9 @@ type DashboardTabRepeatOptions struct {
// NewDashboardTabRepeatOptions creates a new DashboardTabRepeatOptions object.
func NewDashboardTabRepeatOptions() *DashboardTabRepeatOptions {
- return &DashboardTabRepeatOptions{}
+ return &DashboardTabRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
}
// Links with references to other dashboards or external resources
@@ -1214,24 +1222,26 @@ func NewDashboardQueryVariableKind() *DashboardQueryVariableKind {
// Query variable specification
// +k8s:openapi-gen=true
type DashboardQueryVariableSpec struct {
- Name string `json:"name"`
- Current DashboardVariableOption `json:"current"`
- Label *string `json:"label,omitempty"`
- Hide DashboardVariableHide `json:"hide"`
- Refresh DashboardVariableRefresh `json:"refresh"`
- SkipUrlSync bool `json:"skipUrlSync"`
- Description *string `json:"description,omitempty"`
- Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
- Query DashboardDataQueryKind `json:"query"`
- Regex string `json:"regex"`
- Sort DashboardVariableSort `json:"sort"`
- Definition *string `json:"definition,omitempty"`
- Options []DashboardVariableOption `json:"options"`
- Multi bool `json:"multi"`
- IncludeAll bool `json:"includeAll"`
- AllValue *string `json:"allValue,omitempty"`
- Placeholder *string `json:"placeholder,omitempty"`
- AllowCustomValue bool `json:"allowCustomValue"`
+ Name string `json:"name"`
+ Current DashboardVariableOption `json:"current"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ Refresh DashboardVariableRefresh `json:"refresh"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ Query DashboardDataQueryKind `json:"query"`
+ Regex string `json:"regex"`
+ Sort DashboardVariableSort `json:"sort"`
+ Definition *string `json:"definition,omitempty"`
+ Options []DashboardVariableOption `json:"options"`
+ Multi bool `json:"multi"`
+ IncludeAll bool `json:"includeAll"`
+ AllValue *string `json:"allValue,omitempty"`
+ Placeholder *string `json:"placeholder,omitempty"`
+ AllowCustomValue bool `json:"allowCustomValue"`
+ StaticOptions []DashboardVariableOption `json:"staticOptions,omitempty"`
+ StaticOptionsOrder *DashboardQueryVariableSpecStaticOptionsOrder `json:"staticOptionsOrder,omitempty"`
}
// NewDashboardQueryVariableSpec creates a new DashboardQueryVariableSpec object.
@@ -1687,7 +1697,9 @@ type DashboardAdHocFilterWithLabels struct {
// NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object.
func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels {
- return &DashboardAdHocFilterWithLabels{}
+ return &DashboardAdHocFilterWithLabels{
+ Origin: DashboardFilterOrigin,
+ }
}
// Determine the origin of the adhoc variable filter
@@ -1880,6 +1892,15 @@ const (
DashboardTimeSettingsSpecWeekStartSunday DashboardTimeSettingsSpecWeekStart = "sunday"
)
+// +k8s:openapi-gen=true
+type DashboardQueryVariableSpecStaticOptionsOrder string
+
+const (
+ DashboardQueryVariableSpecStaticOptionsOrderBefore DashboardQueryVariableSpecStaticOptionsOrder = "before"
+ DashboardQueryVariableSpecStaticOptionsOrderAfter DashboardQueryVariableSpecStaticOptionsOrder = "after"
+ DashboardQueryVariableSpecStaticOptionsOrderSorted DashboardQueryVariableSpecStaticOptionsOrder = "sorted"
+)
+
// +k8s:openapi-gen=true
type DashboardPanelKindOrLibraryPanelKind struct {
PanelKind *DashboardPanelKind `json:"PanelKind,omitempty"`
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go
index 85b5a6f65cb..ba0a80e050b 100644
--- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go
@@ -3327,6 +3327,25 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
Format: "",
},
},
+ "staticOptions": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "staticOptionsOrder": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
},
Required: []string{"name", "current", "hide", "refresh", "skipUrlSync", "query", "regex", "sort", "options", "multi", "includeAll", "allowCustomValue"},
},
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi_violation_exceptions.list b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi_violation_exceptions.list
index d0755a7cd1f..95eb59de600 100644
--- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi_violation_exceptions.list
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi_violation_exceptions.list
@@ -20,6 +20,7 @@ API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardQueryGroupSpec,Queries
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardQueryGroupSpec,Transformations
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardQueryVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardQueryVariableSpec,StaticOptions
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardRowsLayoutSpec,Rows
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardSpec,Annotations
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardSpec,Links
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/constants.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/constants.go
new file mode 100644
index 00000000000..3942a399896
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/constants.go
@@ -0,0 +1,18 @@
+package v2alpha2
+
+import "k8s.io/apimachinery/pkg/runtime/schema"
+
+const (
+ // APIGroup is the API group used by all kinds in this package
+ APIGroup = "dashboard.grafana.app"
+ // APIVersion is the API version used by all kinds in this package
+ APIVersion = "v2alpha2"
+)
+
+var (
+ // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
+ GroupVersion = schema.GroupVersion{
+ Group: APIGroup,
+ Version: APIVersion,
+ }
+)
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_codec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_codec_gen.go
new file mode 100644
index 00000000000..9c679dcafd7
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v2alpha2
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// DashboardJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type DashboardJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*DashboardJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*DashboardJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &DashboardJSONCodec{}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_metadata_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_metadata_gen.go
new file mode 100644
index 00000000000..62e187af661
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v2alpha2
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type DashboardMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewDashboardMetadata creates a new DashboardMetadata object.
+func NewDashboardMetadata() *DashboardMetadata {
+ return &DashboardMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_object_gen.go
new file mode 100644
index 00000000000..641ba8ce808
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v2alpha2
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type Dashboard struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the Dashboard
+ Spec DashboardSpec `json:"spec" yaml:"spec"`
+
+ Status DashboardStatus `json:"status" yaml:"status"`
+}
+
+func (o *Dashboard) GetSpec() any {
+ return o.Spec
+}
+
+func (o *Dashboard) SetSpec(spec any) error {
+ cast, ok := spec.(DashboardSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *Dashboard) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *Dashboard) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *Dashboard) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(DashboardStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type DashboardStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *Dashboard) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *Dashboard) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *Dashboard) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *Dashboard) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *Dashboard) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *Dashboard) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *Dashboard) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *Dashboard) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *Dashboard) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *Dashboard) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *Dashboard) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *Dashboard) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *Dashboard) DeepCopy() *Dashboard {
+ cpy := &Dashboard{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *Dashboard) DeepCopyInto(dst *Dashboard) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &Dashboard{}
+
+// +k8s:openapi-gen=true
+type DashboardList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []Dashboard `json:"items" yaml:"items"`
+}
+
+func (o *DashboardList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *DashboardList) Copy() resource.ListObject {
+ cpy := &DashboardList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]Dashboard, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*Dashboard); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *DashboardList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *DashboardList) SetItems(items []resource.Object) {
+ o.Items = make([]Dashboard, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*Dashboard)
+ }
+}
+
+func (o *DashboardList) DeepCopy() *DashboardList {
+ cpy := &DashboardList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *DashboardList) DeepCopyInto(dst *DashboardList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &DashboardList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *DashboardSpec) DeepCopy() *DashboardSpec {
+ cpy := &DashboardSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *DashboardSpec) DeepCopyInto(dst *DashboardSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of DashboardStatus
+func (s *DashboardStatus) DeepCopy() *DashboardStatus {
+ cpy := &DashboardStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies DashboardStatus into another DashboardStatus object
+func (s *DashboardStatus) DeepCopyInto(dst *DashboardStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_schema_gen.go
new file mode 100644
index 00000000000..da9ae612d71
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v2alpha2
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha2", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
+ resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
+ kindDashboard = resource.Kind{
+ Schema: schemaDashboard,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &DashboardJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func DashboardKind() resource.Kind {
+ return kindDashboard
+}
+
+// Schema returns a resource.SimpleSchema representation of Dashboard
+func DashboardSchema() *resource.SimpleSchema {
+ return schemaDashboard
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindDashboard
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec.cue b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
new file mode 100644
index 00000000000..4fdce729b2c
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec.cue
@@ -0,0 +1,968 @@
+// This file is managed by grafana-app-sdk - DO NOT EDIT MANUALLY
+// Source: apps/dashboard/kinds/v2alpha2/dashboard_spec.cue
+// To sync changes, run: make generate in apps/dashboard
+
+package v2alpha2
+
+DashboardSpec: {
+ annotations: [...AnnotationQueryKind] | *[]
+
+ // Configuration of dashboard cursor sync behavior.
+ // "Off" for no shared crosshair or tooltip (default).
+ // "Crosshair" for shared crosshair.
+ // "Tooltip" for shared crosshair AND shared tooltip.
+ cursorSync: DashboardCursorSync
+
+ // Description of dashboard.
+ description?: string
+
+ // Whether a dashboard is editable or not.
+ editable?: bool | *true
+
+ elements: [ElementReference.name]: Element | *{}
+
+ layout: GridLayoutKind | RowsLayoutKind | AutoGridLayoutKind | TabsLayoutKind
+
+ // Links with references to other dashboards or external websites.
+ links: [...DashboardLink] | *[]
+
+ // When set to true, the dashboard will redraw panels at an interval matching the pixel width.
+ // This will keep data "moving left" regardless of the query refresh rate. This setting helps
+ // avoid dashboards presenting stale live data.
+ liveNow?: bool
+
+ // When set to true, the dashboard will load all panels in the dashboard when it's loaded.
+ preload: bool | *false
+
+ // Plugins only. The version of the dashboard installed together with the plugin.
+ // This is used to determine if the dashboard should be updated when the plugin is updated.
+ revision?: uint16
+
+ // Tags associated with dashboard.
+ tags: [...string] | *[]
+
+ timeSettings: TimeSettingsSpec
+
+ // Title of dashboard.
+ title: string
+
+ // Configured template variables.
+ variables: [...VariableKind] | *[]
+}
+
+// Supported dashboard elements
+Element: PanelKind | LibraryPanelKind // |* more element types in the future
+
+LibraryPanelKind: {
+ kind: "LibraryPanel"
+ spec: LibraryPanelKindSpec
+}
+
+LibraryPanelKindSpec: {
+ // Panel ID for the library panel in the dashboard
+ id: number
+ // Title for the library panel in the dashboard
+ title: string
+
+ libraryPanel: LibraryPanelRef
+}
+
+// A library panel is a reusable panel that you can use in any dashboard.
+// When you make a change to a library panel, that change propagates to all instances of where the panel is used.
+// Library panels streamline reuse of panels across multiple dashboards.
+LibraryPanelRef: {
+ // Library panel name
+ name: string
+ // Library panel uid
+ uid: string
+}
+
+AnnotationPanelFilter: {
+ // Should the specified panels be included or excluded
+ exclude?: bool | *false
+
+ // Panel IDs that should be included or excluded
+ ids: [...uint32]
+}
+
+// "Off" for no shared crosshair or tooltip (default).
+// "Crosshair" for shared crosshair.
+// "Tooltip" for shared crosshair AND shared tooltip.
+DashboardCursorSync: "Crosshair" | "Tooltip" | *"Off"
+
+// Links with references to other dashboards or external resources
+DashboardLink: {
+ // Title to display with the link
+ title: string
+ // Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+ // FIXME: The type is generated as `type: DashboardLinkType | dashboardLinkType.Link;` but it should be `type: DashboardLinkType`
+ type: DashboardLinkType
+ // Icon name to be displayed with the link
+ icon: string
+ // Tooltip to display when the user hovers their mouse over it
+ tooltip: string
+ // Link URL. Only required/valid if the type is link
+ url?: string
+ // List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards
+ tags: [...string] | *[]
+ // If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards
+ asDropdown: bool | *false
+ // If true, the link will be opened in a new tab
+ targetBlank: bool | *false
+ // If true, includes current template variables values in the link as query params
+ includeVars: bool | *false
+ // If true, includes current time range in the link as query params
+ keepTime: bool | *false
+}
+
+DataSourceRef: {
+ // The plugin type-id
+ type?: string
+
+ // Specific datasource instance
+ uid?: string
+}
+
+// A topic is attached to DataFrame metadata in query results.
+// This specifies where the data should be used.
+DataTopic: "series" | "annotations" | "alertStates" @cog(kind="enum",memberNames="Series|Annotations|AlertStates")
+
+// Transformations allow to manipulate data returned by a query before the system applies a visualization.
+// Using transformations you can: rename fields, join time series data, perform mathematical operations across queries,
+// use the output of one transformation as the input to another transformation, etc.
+DataTransformerConfig: {
+ // Unique identifier of transformer
+ id: string
+ // Disabled transformations are skipped
+ disabled?: bool
+ // Optional frame matcher. When missing it will be applied to all results
+ filter?: MatcherConfig
+ // Where to pull DataFrames from as input to transformation
+ topic?: DataTopic
+ // Options to be passed to the transformer
+ // Valid options depend on the transformer id
+ options: _
+}
+
+DataLink: {
+ title: string
+ url: string
+ targetBlank?: bool
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+FieldConfigSource: {
+ // Defaults are the options applied to all fields.
+ defaults: FieldConfig
+ // Overrides are the options applied to specific fields overriding the defaults.
+ overrides: [...{
+ matcher: MatcherConfig
+ properties: [...DynamicConfigValue]
+ }]
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+FieldConfig: {
+ // The display value for this field. This supports template variables blank is auto
+ displayName?: string
+
+ // This can be used by data sources that return and explicit naming structure for values and labels
+ // When this property is configured, this value is used rather than the default naming strategy.
+ displayNameFromDS?: string
+
+ // Human readable field metadata
+ description?: string
+
+ // An explicit path to the field in the datasource. When the frame meta includes a path,
+ // This will default to `${frame.meta.path}/${field.name}
+ //
+ // When defined, this value can be used as an identifier within the datasource scope, and
+ // may be used to update the results
+ path?: string
+
+ // True if data source can write a value to the path. Auth/authz are supported separately
+ writeable?: bool
+
+ // True if data source field supports ad-hoc filters
+ filterable?: bool
+
+ // Unit a field should use. The unit you select is applied to all fields except time.
+ // You can use the units ID availables in Grafana or a custom unit.
+ // Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts
+ // As custom unit, you can use the following formats:
+ // `suffix:` for custom unit that should go after value.
+ // `prefix:` for custom unit that should go before value.
+ // `time:` For custom date time formats type for example `time:YYYY-MM-DD`.
+ // `si:` for custom SI units. For example: `si: mF`. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.
+ // `count:` for a custom count unit.
+ // `currency:` for custom a currency unit.
+ unit?: string
+
+ // Specify the number of decimals Grafana includes in the rendered value.
+ // If you leave this field blank, Grafana automatically truncates the number of decimals based on the value.
+ // For example 1.1234 will display as 1.12 and 100.456 will display as 100.
+ // To display all decimals, set the unit to `String`.
+ decimals?: number
+
+ // The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ min?: number
+ // The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ max?: number
+
+ // Convert input values into a display string
+ mappings?: [...ValueMapping]
+
+ // Map numeric values to states
+ thresholds?: ThresholdsConfig
+
+ // Panel color configuration
+ color?: FieldColor
+
+ // The behavior when clicking on a result
+ links?: [...]
+
+ // Alternative to empty string
+ noValue?: string
+
+ // custom is specified by the FieldConfig field
+ // in panel plugin schemas.
+ custom?: {...}
+}
+
+DynamicConfigValue: {
+ id: string | *""
+ value?: _
+}
+
+// Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.
+// It comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.
+MatcherConfig: {
+ // The matcher id. This is used to find the matcher implementation from registry.
+ id: string | *""
+ // The matcher options. This is specific to the matcher implementation.
+ options?: _
+}
+
+Threshold: {
+ value: number
+ color: string
+}
+
+ThresholdsMode: "absolute" | "percentage"
+
+ThresholdsConfig: {
+ mode: ThresholdsMode
+ steps: [...Threshold]
+}
+
+ValueMapping: ValueMap | RangeMap | RegexMap | SpecialValueMap
+
+// Supported value mapping types
+// `value`: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+// `range`: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+// `regex`: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+// `special`: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.
+MappingType: "value" | "range" | "regex" | "special"
+
+// Maps text values to a color or different display text and color.
+// For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+ValueMap: {
+ type: MappingType & "value"
+ // Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } }
+ options: [string]: ValueMappingResult
+}
+
+// Maps numerical ranges to a display text and color.
+// For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+RangeMap: {
+ type: MappingType & "range"
+ // Range to match against and the result to apply when the value is within the range
+ options: {
+ // Min value of the range. It can be null which means -Infinity
+ from: float64 | null
+ // Max value of the range. It can be null which means +Infinity
+ to: float64 | null
+ // Config to apply when the value is within the range
+ result: ValueMappingResult
+ }
+}
+
+// Maps regular expressions to replacement text and a color.
+// For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+RegexMap: {
+ type: MappingType & "regex"
+ // Regular expression to match against and the result to apply when the value matches the regex
+ options: {
+ // Regular expression to match against
+ pattern: string
+ // Config to apply when the value matches the regex
+ result: ValueMappingResult
+ }
+}
+
+// Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.
+// See SpecialValueMatch to see the list of special values.
+// For example, you can configure a special value mapping so that null values appear as N/A.
+SpecialValueMap: {
+ type: MappingType & "special"
+ options: {
+ // Special value to match against
+ match: SpecialValueMatch
+ // Config to apply when the value matches the special value
+ result: ValueMappingResult
+ }
+}
+
+// Special value types supported by the `SpecialValueMap`
+SpecialValueMatch: "true" | "false" | "null" | "nan" | "null+nan" | "empty" @cog(kind="enum",memberNames="True|False|Null|NaN|NullAndNaN|Empty")
+
+// Result used as replacement with text and color when the value matches
+ValueMappingResult: {
+ // Text to display when the value matches
+ text?: string
+ // Text to use when the value matches
+ color?: string
+ // Icon to display when the value matches. Only specific visualizations.
+ icon?: string
+ // Position in the mapping array. Only used internally.
+ index?: int32
+}
+
+// Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
+// Continuous color interpolates a color using the percentage of a value relative to min and max.
+// Accepted values are:
+// `thresholds`: From thresholds. Informs Grafana to take the color from the matching threshold
+// `palette-classic`: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations
+// `palette-classic-by-name`: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations
+// `continuous-GrYlRd`: ontinuous Green-Yellow-Red palette mode
+// `continuous-RdYlGr`: Continuous Red-Yellow-Green palette mode
+// `continuous-BlYlRd`: Continuous Blue-Yellow-Red palette mode
+// `continuous-YlRd`: Continuous Yellow-Red palette mode
+// `continuous-BlPu`: Continuous Blue-Purple palette mode
+// `continuous-YlBl`: Continuous Yellow-Blue palette mode
+// `continuous-blues`: Continuous Blue palette mode
+// `continuous-reds`: Continuous Red palette mode
+// `continuous-greens`: Continuous Green palette mode
+// `continuous-purples`: Continuous Purple palette mode
+// `shades`: Shades of a single color. Specify a single color, useful in an override rule.
+// `fixed`: Fixed color mode. Specify a single color, useful in an override rule.
+FieldColorModeId: "thresholds" | "palette-classic" | "palette-classic-by-name" | "continuous-GrYlRd" | "continuous-RdYlGr" | "continuous-BlYlRd" | "continuous-YlRd" | "continuous-BlPu" | "continuous-YlBl" | "continuous-blues" | "continuous-reds" | "continuous-greens" | "continuous-purples" | "fixed" | "shades"
+
+// Defines how to assign a series color from "by value" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.
+FieldColorSeriesByMode: "min" | "max" | "last"
+
+// Map a field to a color.
+FieldColor: {
+ // The main color scheme mode.
+ mode: FieldColorModeId
+ // The fixed color value for fixed or shades color modes.
+ fixedColor?: string
+ // Some visualizations need to know how to assign a series color from by value color schemes.
+ seriesBy?: FieldColorSeriesByMode
+}
+
+// Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+DashboardLinkType: "link" | "dashboards"
+
+// --- Common types ---
+Kind: {
+ kind: string
+ spec: _
+ metadata?: _
+}
+
+// --- Kinds ---
+VizConfigSpec: {
+ pluginVersion: string
+ options: [string]: _
+ fieldConfig: FieldConfigSource
+}
+
+VizConfigKind: {
+ // The kind of a VizConfigKind is the plugin ID
+ kind: string
+ spec: VizConfigSpec
+}
+
+AnnotationQuerySpec: {
+ datasource?: DataSourceRef
+ query?: DataQueryKind
+ enable: bool
+ hide: bool
+ iconColor: string
+ name: string
+ builtIn?: bool | *false
+ filter?: AnnotationPanelFilter
+ legacyOptions?: [string]: _ //Catch-all field for datasource-specific properties
+}
+
+AnnotationQueryKind: {
+ kind: "AnnotationQuery"
+ spec: AnnotationQuerySpec
+}
+
+QueryOptionsSpec: {
+ timeFrom?: string
+ maxDataPoints?: int
+ timeShift?: string
+ queryCachingTTL?: int
+ interval?: string
+ cacheTimeout?: string
+ hideTimeOverride?: bool
+}
+
+DataQueryKind: {
+ // The kind of a DataQueryKind is the datasource type
+ kind: string
+ spec: [string]: _
+}
+
+PanelQuerySpec: {
+ query: DataQueryKind
+ datasource?: DataSourceRef
+
+ refId: string
+ hidden: bool
+}
+
+PanelQueryKind: {
+ kind: "PanelQuery"
+ spec: PanelQuerySpec
+}
+
+TransformationKind: {
+ // The kind of a TransformationKind is the transformation ID
+ kind: string
+ spec: DataTransformerConfig
+}
+
+QueryGroupSpec: {
+ queries: [...PanelQueryKind]
+ transformations: [...TransformationKind]
+ queryOptions: QueryOptionsSpec
+}
+
+QueryGroupKind: {
+ kind: "QueryGroup"
+ spec: QueryGroupSpec
+}
+
+TimeRangeOption: {
+ display: string | *"Last 6 hours"
+ from: string | *"now-6h"
+ to: string | *"now"
+}
+
+// Time configuration
+// It defines the default time config for the time picker, the refresh picker for the specific dashboard.
+TimeSettingsSpec: {
+ // Timezone of dashboard. Accepted values are IANA TZDB zone ID or "browser" or "utc".
+ timezone?: string | *"browser"
+ // Start time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ from: string | *"now-6h"
+ // End time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ to: string | *"now"
+ // Refresh rate of dashboard. Represented via interval string, e.g. "5s", "1m", "1h", "1d".
+ autoRefresh: string | *"" // v1: refresh
+ // Interval options available in the refresh picker dropdown.
+ autoRefreshIntervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] // v1: timepicker.refresh_intervals
+ // Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
+ quickRanges?: [...TimeRangeOption] // v1: timepicker.quick_ranges , not exposed in the UI
+ // Whether timepicker is visible or not.
+ hideTimepicker: bool | *false // v1: timepicker.hidden
+ // Day when the week starts. Expressed by the name of the day in lowercase, e.g. "monday".
+ weekStart?: "saturday" | "monday" | "sunday"
+ // The month that the fiscal year starts on. 0 = January, 11 = December
+ fiscalYearStartMonth: int | *0
+ // Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
+ nowDelay?: string // v1: timepicker.nowDelay
+}
+
+RepeatMode: "variable" // other repeat modes will be added in the future: label, frame
+
+RepeatOptions: {
+ mode: RepeatMode
+ value: string
+ direction?: "h" | "v"
+ maxPerRow?: int
+}
+
+RowRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+TabRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+AutoGridRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+GridLayoutItemSpec: {
+ x: int
+ y: int
+ width: int
+ height: int
+ element: ElementReference // reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference
+ repeat?: RepeatOptions
+}
+
+GridLayoutItemKind: {
+ kind: "GridLayoutItem"
+ spec: GridLayoutItemSpec
+}
+
+GridLayoutSpec: {
+ items: [...GridLayoutItemKind]
+}
+
+GridLayoutKind: {
+ kind: "GridLayout"
+ spec: GridLayoutSpec
+}
+
+RowsLayoutKind: {
+ kind: "RowsLayout"
+ spec: RowsLayoutSpec
+}
+
+RowsLayoutSpec: {
+ rows: [...RowsLayoutRowKind]
+}
+
+RowsLayoutRowKind: {
+ kind: "RowsLayoutRow"
+ spec: RowsLayoutRowSpec
+}
+
+RowsLayoutRowSpec: {
+ title?: string
+ collapse?: bool
+ hideHeader?: bool
+ fillScreen?: bool
+ conditionalRendering?: ConditionalRenderingGroupKind
+ repeat?: RowRepeatOptions
+ layout: GridLayoutKind | AutoGridLayoutKind | TabsLayoutKind | RowsLayoutKind
+}
+
+AutoGridLayoutKind: {
+ kind: "AutoGridLayout"
+ spec: AutoGridLayoutSpec
+}
+
+AutoGridLayoutSpec: {
+ maxColumnCount?: number | *3
+ columnWidthMode: "narrow" | *"standard" | "wide" | "custom"
+ columnWidth?: number
+ rowHeightMode: "short" | *"standard" | "tall" | "custom"
+ rowHeight?: number
+ fillScreen?: bool | *false
+ items: [...AutoGridLayoutItemKind]
+}
+
+AutoGridLayoutItemKind: {
+ kind: "AutoGridLayoutItem"
+ spec: AutoGridLayoutItemSpec
+}
+
+AutoGridLayoutItemSpec: {
+ element: ElementReference
+ repeat?: AutoGridRepeatOptions
+ conditionalRendering?: ConditionalRenderingGroupKind
+}
+
+TabsLayoutKind: {
+ kind: "TabsLayout"
+ spec: TabsLayoutSpec
+}
+
+TabsLayoutSpec: {
+ tabs: [...TabsLayoutTabKind]
+}
+
+TabsLayoutTabKind: {
+ kind: "TabsLayoutTab"
+ spec: TabsLayoutTabSpec
+}
+
+TabsLayoutTabSpec: {
+ title?: string
+ layout: GridLayoutKind | RowsLayoutKind | AutoGridLayoutKind | TabsLayoutKind
+ conditionalRendering?: ConditionalRenderingGroupKind
+ repeat?: TabRepeatOptions
+}
+
+PanelSpec: {
+ id: number
+ title: string
+ description: string
+ links: [...DataLink]
+ data: QueryGroupKind
+ vizConfig: VizConfigKind
+ transparent?: bool
+}
+
+PanelKind: {
+ kind: "Panel"
+ spec: PanelSpec
+}
+
+ElementReference: {
+ kind: "ElementReference"
+ name: string
+}
+
+// Start FIXME: variables - in CUE PR - this are things that should be added into the cue schema
+// TODO: properties such as `hide`, `skipUrlSync`, `multi` are type boolean, and in the old schema they are conditional,
+// should we make them conditional in the new schema as well? or should we make them required but default to false?
+
+// Variable types
+VariableValue: VariableValueSingle | [...VariableValueSingle]
+
+VariableValueSingle: string | bool | number | CustomVariableValue
+
+// Custom formatter variable
+CustomFormatterVariable: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+}
+
+// Custom variable value
+CustomVariableValue: {
+ // The format name or function used in the expression
+ formatter: *null | string | VariableCustomFormatterFn
+}
+
+// Custom formatter function
+VariableCustomFormatterFn: {
+ value: _
+ legacyVariableModel: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+ }
+ legacyDefaultFormatter?: VariableCustomFormatterFn
+}
+
+// Dashboard variable type
+// `query`: Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on.
+// `adhoc`: Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only).
+// `constant`: Define a hidden constant.
+// `datasource`: Quickly change the data source for an entire dashboard.
+// `interval`: Interval variables represent time spans.
+// `textbox`: Display a free text input field with an optional default value.
+// `custom`: Define the variable options manually using a comma-separated list.
+// `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
+VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" |
+ "system" | "snapshot"
+
+VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind
+
+// Sort variable options
+// Accepted values are:
+// `disabled`: No sorting
+// `alphabeticalAsc`: Alphabetical ASC
+// `alphabeticalDesc`: Alphabetical DESC
+// `numericalAsc`: Numerical ASC
+// `numericalDesc`: Numerical DESC
+// `alphabeticalCaseInsensitiveAsc`: Alphabetical Case Insensitive ASC
+// `alphabeticalCaseInsensitiveDesc`: Alphabetical Case Insensitive DESC
+// `naturalAsc`: Natural ASC
+// `naturalDesc`: Natural DESC
+// VariableSort enum with default value
+VariableSort: "disabled" | "alphabeticalAsc" | "alphabeticalDesc" | "numericalAsc" | "numericalDesc" | "alphabeticalCaseInsensitiveAsc" | "alphabeticalCaseInsensitiveDesc" | "naturalAsc" | "naturalDesc"
+
+// Options to config when to refresh a variable
+// `never`: Never refresh the variable
+// `onDashboardLoad`: Queries the data source every time the dashboard loads.
+// `onTimeRangeChanged`: Queries the data source when the dashboard time range changes.
+VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
+
+// Determine if the variable shows on dashboard
+// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
+VariableHide: *"dontHide" | "hideLabel" | "hideVariable"
+
+// Determine the origin of the adhoc variable filter
+FilterOrigin: "dashboard"
+
+// FIXME: should we introduce this? --- Variable value option
+VariableValueOption: {
+ label: string
+ value: VariableValueSingle
+ group?: string
+}
+
+// Variable option specification
+VariableOption: {
+ // Whether the option is selected or not
+ selected?: bool
+ // Text to be displayed for the option
+ text: string | [...string]
+ // Value of the option
+ value: string | [...string]
+}
+
+// Query variable specification
+QueryVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ refresh: VariableRefresh
+ skipUrlSync: bool | *false
+ description?: string
+ datasource?: DataSourceRef
+ query: DataQueryKind
+ regex: string | *""
+ sort: VariableSort
+ definition?: string
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ placeholder?: string
+ allowCustomValue: bool | *true
+ staticOptions?: [...VariableOption]
+ staticOptionsOrder?: "before" | "after" | "sorted"
+}
+
+// Query variable kind
+QueryVariableKind: {
+ kind: "QueryVariable"
+ spec: QueryVariableSpec
+}
+
+// Text variable specification
+TextVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ query: string | *""
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Text variable kind
+TextVariableKind: {
+ kind: "TextVariable"
+ spec: TextVariableSpec
+}
+
+// Constant variable specification
+ConstantVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Constant variable kind
+ConstantVariableKind: {
+ kind: "ConstantVariable"
+ spec: ConstantVariableSpec
+}
+
+// Datasource variable specification
+DatasourceVariableSpec: {
+ name: string | *""
+ pluginId: string | *""
+ refresh: VariableRefresh
+ regex: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Datasource variable kind
+DatasourceVariableKind: {
+ kind: "DatasourceVariable"
+ spec: DatasourceVariableSpec
+}
+
+// Interval variable specification
+IntervalVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ auto: bool | *false
+ auto_min: string | *""
+ auto_count: int | *0
+ refresh: VariableRefresh
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Interval variable kind
+IntervalVariableKind: {
+ kind: "IntervalVariable"
+ spec: IntervalVariableSpec
+}
+
+// Custom variable specification
+CustomVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Custom variable kind
+CustomVariableKind: {
+ kind: "CustomVariable"
+ spec: CustomVariableSpec
+}
+
+// GroupBy variable specification
+GroupByVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ defaultValue?: VariableOption
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Group variable kind
+GroupByVariableKind: {
+ kind: "GroupByVariable"
+ spec: GroupByVariableSpec
+}
+
+// Adhoc variable specification
+AdhocVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ baseFilters: [...AdHocFilterWithLabels] | *[]
+ filters: [...AdHocFilterWithLabels] | *[]
+ defaultKeys: [...MetricFindValue] | *[]
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+ allowCustomValue: bool | *true
+}
+
+// Define the MetricFindValue type
+MetricFindValue: {
+ text: string
+ value?: string | number
+ group?: string
+ expandable?: bool
+}
+
+// Define the AdHocFilterWithLabels type
+AdHocFilterWithLabels: {
+ key: string
+ operator: string
+ value: string
+ values?: [...string]
+ keyLabel?: string
+ valueLabels?: [...string]
+ forceEdit?: bool
+ origin?: FilterOrigin
+ // @deprecated
+ condition?: string
+}
+
+// Adhoc variable kind
+AdhocVariableKind: {
+ kind: "AdhocVariable"
+ spec: AdhocVariableSpec
+}
+
+ConditionalRenderingGroupKind: {
+ kind: "ConditionalRenderingGroup"
+ spec: ConditionalRenderingGroupSpec
+}
+
+ConditionalRenderingGroupSpec: {
+ visibility: "show" | "hide"
+ condition: "and" | "or"
+ items: [...ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeRangeSizeKind]
+}
+
+ConditionalRenderingVariableKind: {
+ kind: "ConditionalRenderingVariable"
+ spec: ConditionalRenderingVariableSpec
+}
+
+ConditionalRenderingVariableSpec: {
+ variable: string
+ operator: "equals" | "notEquals"
+ value: string
+}
+
+ConditionalRenderingDataKind: {
+ kind: "ConditionalRenderingData"
+ spec: ConditionalRenderingDataSpec
+}
+
+ConditionalRenderingDataSpec: {
+ value: bool
+}
+
+ConditionalRenderingTimeRangeSizeKind: {
+ kind: "ConditionalRenderingTimeRangeSize"
+ spec: ConditionalRenderingTimeRangeSizeSpec
+}
+
+ConditionalRenderingTimeRangeSizeSpec: {
+ value: string
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec_gen.go
new file mode 100644
index 00000000000..32b90053977
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_spec_gen.go
@@ -0,0 +1,2540 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v2alpha2
+
+import (
+ json "encoding/json"
+ errors "errors"
+)
+
+// +k8s:openapi-gen=true
+type DashboardAnnotationQueryKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardAnnotationQuerySpec `json:"spec"`
+}
+
+// NewDashboardAnnotationQueryKind creates a new DashboardAnnotationQueryKind object.
+func NewDashboardAnnotationQueryKind() *DashboardAnnotationQueryKind {
+ return &DashboardAnnotationQueryKind{
+ Kind: "AnnotationQuery",
+ Spec: *NewDashboardAnnotationQuerySpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAnnotationQuerySpec struct {
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ Query *DashboardDataQueryKind `json:"query,omitempty"`
+ Enable bool `json:"enable"`
+ Hide bool `json:"hide"`
+ IconColor string `json:"iconColor"`
+ Name string `json:"name"`
+ BuiltIn *bool `json:"builtIn,omitempty"`
+ Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"`
+ // Catch-all field for datasource-specific properties
+ LegacyOptions map[string]interface{} `json:"legacyOptions,omitempty"`
+}
+
+// NewDashboardAnnotationQuerySpec creates a new DashboardAnnotationQuerySpec object.
+func NewDashboardAnnotationQuerySpec() *DashboardAnnotationQuerySpec {
+ return &DashboardAnnotationQuerySpec{
+ BuiltIn: (func(input bool) *bool { return &input })(false),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardDataSourceRef struct {
+ // The plugin type-id
+ Type *string `json:"type,omitempty"`
+ // Specific datasource instance
+ Uid *string `json:"uid,omitempty"`
+}
+
+// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object.
+func NewDashboardDataSourceRef() *DashboardDataSourceRef {
+ return &DashboardDataSourceRef{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardDataQueryKind struct {
+ // The kind of a DataQueryKind is the datasource type
+ Kind string `json:"kind"`
+ Spec map[string]interface{} `json:"spec"`
+}
+
+// NewDashboardDataQueryKind creates a new DashboardDataQueryKind object.
+func NewDashboardDataQueryKind() *DashboardDataQueryKind {
+ return &DashboardDataQueryKind{
+ Spec: map[string]interface{}{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAnnotationPanelFilter struct {
+ // Should the specified panels be included or excluded
+ Exclude *bool `json:"exclude,omitempty"`
+ // Panel IDs that should be included or excluded
+ Ids []uint32 `json:"ids"`
+}
+
+// NewDashboardAnnotationPanelFilter creates a new DashboardAnnotationPanelFilter object.
+func NewDashboardAnnotationPanelFilter() *DashboardAnnotationPanelFilter {
+ return &DashboardAnnotationPanelFilter{
+ Exclude: (func(input bool) *bool { return &input })(false),
+ Ids: []uint32{},
+ }
+}
+
+// "Off" for no shared crosshair or tooltip (default).
+// "Crosshair" for shared crosshair.
+// "Tooltip" for shared crosshair AND shared tooltip.
+// +k8s:openapi-gen=true
+type DashboardDashboardCursorSync string
+
+const (
+ DashboardDashboardCursorSyncCrosshair DashboardDashboardCursorSync = "Crosshair"
+ DashboardDashboardCursorSyncTooltip DashboardDashboardCursorSync = "Tooltip"
+ DashboardDashboardCursorSyncOff DashboardDashboardCursorSync = "Off"
+)
+
+// Supported dashboard elements
+// |* more element types in the future
+// +k8s:openapi-gen=true
+type DashboardElement = DashboardPanelKindOrLibraryPanelKind
+
+// NewDashboardElement creates a new DashboardElement object.
+func NewDashboardElement() *DashboardElement {
+ return NewDashboardPanelKindOrLibraryPanelKind()
+}
+
+// +k8s:openapi-gen=true
+type DashboardPanelKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardPanelSpec `json:"spec"`
+}
+
+// NewDashboardPanelKind creates a new DashboardPanelKind object.
+func NewDashboardPanelKind() *DashboardPanelKind {
+ return &DashboardPanelKind{
+ Kind: "Panel",
+ Spec: *NewDashboardPanelSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardPanelSpec struct {
+ Id float64 `json:"id"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Links []DashboardDataLink `json:"links"`
+ Data DashboardQueryGroupKind `json:"data"`
+ VizConfig DashboardVizConfigKind `json:"vizConfig"`
+ Transparent *bool `json:"transparent,omitempty"`
+}
+
+// NewDashboardPanelSpec creates a new DashboardPanelSpec object.
+func NewDashboardPanelSpec() *DashboardPanelSpec {
+ return &DashboardPanelSpec{
+ Links: []DashboardDataLink{},
+ Data: *NewDashboardQueryGroupKind(),
+ VizConfig: *NewDashboardVizConfigKind(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardDataLink struct {
+ Title string `json:"title"`
+ Url string `json:"url"`
+ TargetBlank *bool `json:"targetBlank,omitempty"`
+}
+
+// NewDashboardDataLink creates a new DashboardDataLink object.
+func NewDashboardDataLink() *DashboardDataLink {
+ return &DashboardDataLink{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardQueryGroupKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardQueryGroupSpec `json:"spec"`
+}
+
+// NewDashboardQueryGroupKind creates a new DashboardQueryGroupKind object.
+func NewDashboardQueryGroupKind() *DashboardQueryGroupKind {
+ return &DashboardQueryGroupKind{
+ Kind: "QueryGroup",
+ Spec: *NewDashboardQueryGroupSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardQueryGroupSpec struct {
+ Queries []DashboardPanelQueryKind `json:"queries"`
+ Transformations []DashboardTransformationKind `json:"transformations"`
+ QueryOptions DashboardQueryOptionsSpec `json:"queryOptions"`
+}
+
+// NewDashboardQueryGroupSpec creates a new DashboardQueryGroupSpec object.
+func NewDashboardQueryGroupSpec() *DashboardQueryGroupSpec {
+ return &DashboardQueryGroupSpec{
+ Queries: []DashboardPanelQueryKind{},
+ Transformations: []DashboardTransformationKind{},
+ QueryOptions: *NewDashboardQueryOptionsSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardPanelQueryKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardPanelQuerySpec `json:"spec"`
+}
+
+// NewDashboardPanelQueryKind creates a new DashboardPanelQueryKind object.
+func NewDashboardPanelQueryKind() *DashboardPanelQueryKind {
+ return &DashboardPanelQueryKind{
+ Kind: "PanelQuery",
+ Spec: *NewDashboardPanelQuerySpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardPanelQuerySpec struct {
+ Query DashboardDataQueryKind `json:"query"`
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ RefId string `json:"refId"`
+ Hidden bool `json:"hidden"`
+}
+
+// NewDashboardPanelQuerySpec creates a new DashboardPanelQuerySpec object.
+func NewDashboardPanelQuerySpec() *DashboardPanelQuerySpec {
+ return &DashboardPanelQuerySpec{
+ Query: *NewDashboardDataQueryKind(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTransformationKind struct {
+ // The kind of a TransformationKind is the transformation ID
+ Kind string `json:"kind"`
+ Spec DashboardDataTransformerConfig `json:"spec"`
+}
+
+// NewDashboardTransformationKind creates a new DashboardTransformationKind object.
+func NewDashboardTransformationKind() *DashboardTransformationKind {
+ return &DashboardTransformationKind{
+ Spec: *NewDashboardDataTransformerConfig(),
+ }
+}
+
+// Transformations allow to manipulate data returned by a query before the system applies a visualization.
+// Using transformations you can: rename fields, join time series data, perform mathematical operations across queries,
+// use the output of one transformation as the input to another transformation, etc.
+// +k8s:openapi-gen=true
+type DashboardDataTransformerConfig struct {
+ // Unique identifier of transformer
+ Id string `json:"id"`
+ // Disabled transformations are skipped
+ Disabled *bool `json:"disabled,omitempty"`
+ // Optional frame matcher. When missing it will be applied to all results
+ Filter *DashboardMatcherConfig `json:"filter,omitempty"`
+ // Where to pull DataFrames from as input to transformation
+ Topic *DashboardDataTopic `json:"topic,omitempty"`
+ // Options to be passed to the transformer
+ // Valid options depend on the transformer id
+ Options interface{} `json:"options"`
+}
+
+// NewDashboardDataTransformerConfig creates a new DashboardDataTransformerConfig object.
+func NewDashboardDataTransformerConfig() *DashboardDataTransformerConfig {
+ return &DashboardDataTransformerConfig{}
+}
+
+// Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.
+// It comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.
+// +k8s:openapi-gen=true
+type DashboardMatcherConfig struct {
+ // The matcher id. This is used to find the matcher implementation from registry.
+ Id string `json:"id"`
+ // The matcher options. This is specific to the matcher implementation.
+ Options interface{} `json:"options,omitempty"`
+}
+
+// NewDashboardMatcherConfig creates a new DashboardMatcherConfig object.
+func NewDashboardMatcherConfig() *DashboardMatcherConfig {
+ return &DashboardMatcherConfig{
+ Id: "",
+ }
+}
+
+// A topic is attached to DataFrame metadata in query results.
+// This specifies where the data should be used.
+// +k8s:openapi-gen=true
+type DashboardDataTopic string
+
+const (
+ DashboardDataTopicSeries DashboardDataTopic = "series"
+ DashboardDataTopicAnnotations DashboardDataTopic = "annotations"
+ DashboardDataTopicAlertStates DashboardDataTopic = "alertStates"
+)
+
+// +k8s:openapi-gen=true
+type DashboardQueryOptionsSpec struct {
+ TimeFrom *string `json:"timeFrom,omitempty"`
+ MaxDataPoints *int64 `json:"maxDataPoints,omitempty"`
+ TimeShift *string `json:"timeShift,omitempty"`
+ QueryCachingTTL *int64 `json:"queryCachingTTL,omitempty"`
+ Interval *string `json:"interval,omitempty"`
+ CacheTimeout *string `json:"cacheTimeout,omitempty"`
+ HideTimeOverride *bool `json:"hideTimeOverride,omitempty"`
+}
+
+// NewDashboardQueryOptionsSpec creates a new DashboardQueryOptionsSpec object.
+func NewDashboardQueryOptionsSpec() *DashboardQueryOptionsSpec {
+ return &DashboardQueryOptionsSpec{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardVizConfigKind struct {
+ // The kind of a VizConfigKind is the plugin ID
+ Kind string `json:"kind"`
+ Spec DashboardVizConfigSpec `json:"spec"`
+}
+
+// NewDashboardVizConfigKind creates a new DashboardVizConfigKind object.
+func NewDashboardVizConfigKind() *DashboardVizConfigKind {
+ return &DashboardVizConfigKind{
+ Spec: *NewDashboardVizConfigSpec(),
+ }
+}
+
+// --- Kinds ---
+// +k8s:openapi-gen=true
+type DashboardVizConfigSpec struct {
+ PluginVersion string `json:"pluginVersion"`
+ Options map[string]interface{} `json:"options"`
+ FieldConfig DashboardFieldConfigSource `json:"fieldConfig"`
+}
+
+// NewDashboardVizConfigSpec creates a new DashboardVizConfigSpec object.
+func NewDashboardVizConfigSpec() *DashboardVizConfigSpec {
+ return &DashboardVizConfigSpec{
+ Options: map[string]interface{}{},
+ FieldConfig: *NewDashboardFieldConfigSource(),
+ }
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+// +k8s:openapi-gen=true
+type DashboardFieldConfigSource struct {
+ // Defaults are the options applied to all fields.
+ Defaults DashboardFieldConfig `json:"defaults"`
+ // Overrides are the options applied to specific fields overriding the defaults.
+ Overrides []DashboardV2alpha2FieldConfigSourceOverrides `json:"overrides"`
+}
+
+// NewDashboardFieldConfigSource creates a new DashboardFieldConfigSource object.
+func NewDashboardFieldConfigSource() *DashboardFieldConfigSource {
+ return &DashboardFieldConfigSource{
+ Defaults: *NewDashboardFieldConfig(),
+ Overrides: []DashboardV2alpha2FieldConfigSourceOverrides{},
+ }
+}
+
+// The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
+// Each column within this structure is called a field. A field can represent a single time series or table column.
+// Field options allow you to change how the data is displayed in your visualizations.
+// +k8s:openapi-gen=true
+type DashboardFieldConfig struct {
+ // The display value for this field. This supports template variables blank is auto
+ DisplayName *string `json:"displayName,omitempty"`
+ // This can be used by data sources that return and explicit naming structure for values and labels
+ // When this property is configured, this value is used rather than the default naming strategy.
+ DisplayNameFromDS *string `json:"displayNameFromDS,omitempty"`
+ // Human readable field metadata
+ Description *string `json:"description,omitempty"`
+ // An explicit path to the field in the datasource. When the frame meta includes a path,
+ // This will default to `${frame.meta.path}/${field.name}
+ //
+ // When defined, this value can be used as an identifier within the datasource scope, and
+ // may be used to update the results
+ Path *string `json:"path,omitempty"`
+ // True if data source can write a value to the path. Auth/authz are supported separately
+ Writeable *bool `json:"writeable,omitempty"`
+ // True if data source field supports ad-hoc filters
+ Filterable *bool `json:"filterable,omitempty"`
+ // Unit a field should use. The unit you select is applied to all fields except time.
+ // You can use the units ID availables in Grafana or a custom unit.
+ // Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts
+ // As custom unit, you can use the following formats:
+ // `suffix:` for custom unit that should go after value.
+ // `prefix:` for custom unit that should go before value.
+ // `time:` For custom date time formats type for example `time:YYYY-MM-DD`.
+ // `si:` for custom SI units. For example: `si: mF`. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.
+ // `count:` for a custom count unit.
+ // `currency:` for custom a currency unit.
+ Unit *string `json:"unit,omitempty"`
+ // Specify the number of decimals Grafana includes in the rendered value.
+ // If you leave this field blank, Grafana automatically truncates the number of decimals based on the value.
+ // For example 1.1234 will display as 1.12 and 100.456 will display as 100.
+ // To display all decimals, set the unit to `String`.
+ Decimals *float64 `json:"decimals,omitempty"`
+ // The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ Min *float64 `json:"min,omitempty"`
+ // The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ Max *float64 `json:"max,omitempty"`
+ // Convert input values into a display string
+ Mappings []DashboardValueMapping `json:"mappings,omitempty"`
+ // Map numeric values to states
+ Thresholds *DashboardThresholdsConfig `json:"thresholds,omitempty"`
+ // Panel color configuration
+ Color *DashboardFieldColor `json:"color,omitempty"`
+ // The behavior when clicking on a result
+ Links []interface{} `json:"links,omitempty"`
+ // Alternative to empty string
+ NoValue *string `json:"noValue,omitempty"`
+ // custom is specified by the FieldConfig field
+ // in panel plugin schemas.
+ Custom map[string]interface{} `json:"custom,omitempty"`
+}
+
+// NewDashboardFieldConfig creates a new DashboardFieldConfig object.
+func NewDashboardFieldConfig() *DashboardFieldConfig {
+ return &DashboardFieldConfig{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardValueMapping = DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap
+
+// NewDashboardValueMapping creates a new DashboardValueMapping object.
+func NewDashboardValueMapping() *DashboardValueMapping {
+ return NewDashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap()
+}
+
+// Maps text values to a color or different display text and color.
+// For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+// +k8s:openapi-gen=true
+type DashboardValueMap struct {
+ Type DashboardMappingType `json:"type"`
+ // Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } }
+ Options map[string]DashboardValueMappingResult `json:"options"`
+}
+
+// NewDashboardValueMap creates a new DashboardValueMap object.
+func NewDashboardValueMap() *DashboardValueMap {
+ return &DashboardValueMap{
+ Type: DashboardMappingTypeValue,
+ Options: map[string]DashboardValueMappingResult{},
+ }
+}
+
+// Supported value mapping types
+// `value`: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+// `range`: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+// `regex`: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+// `special`: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.
+// +k8s:openapi-gen=true
+type DashboardMappingType string
+
+const (
+ DashboardMappingTypeValue DashboardMappingType = "value"
+ DashboardMappingTypeRange DashboardMappingType = "range"
+ DashboardMappingTypeRegex DashboardMappingType = "regex"
+ DashboardMappingTypeSpecial DashboardMappingType = "special"
+)
+
+// Result used as replacement with text and color when the value matches
+// +k8s:openapi-gen=true
+type DashboardValueMappingResult struct {
+ // Text to display when the value matches
+ Text *string `json:"text,omitempty"`
+ // Text to use when the value matches
+ Color *string `json:"color,omitempty"`
+ // Icon to display when the value matches. Only specific visualizations.
+ Icon *string `json:"icon,omitempty"`
+ // Position in the mapping array. Only used internally.
+ Index *int32 `json:"index,omitempty"`
+}
+
+// NewDashboardValueMappingResult creates a new DashboardValueMappingResult object.
+func NewDashboardValueMappingResult() *DashboardValueMappingResult {
+ return &DashboardValueMappingResult{}
+}
+
+// Maps numerical ranges to a display text and color.
+// For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+// +k8s:openapi-gen=true
+type DashboardRangeMap struct {
+ Type DashboardMappingType `json:"type"`
+ // Range to match against and the result to apply when the value is within the range
+ Options DashboardV2alpha2RangeMapOptions `json:"options"`
+}
+
+// NewDashboardRangeMap creates a new DashboardRangeMap object.
+func NewDashboardRangeMap() *DashboardRangeMap {
+ return &DashboardRangeMap{
+ Type: DashboardMappingTypeRange,
+ Options: *NewDashboardV2alpha2RangeMapOptions(),
+ }
+}
+
+// Maps regular expressions to replacement text and a color.
+// For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+// +k8s:openapi-gen=true
+type DashboardRegexMap struct {
+ Type DashboardMappingType `json:"type"`
+ // Regular expression to match against and the result to apply when the value matches the regex
+ Options DashboardV2alpha2RegexMapOptions `json:"options"`
+}
+
+// NewDashboardRegexMap creates a new DashboardRegexMap object.
+func NewDashboardRegexMap() *DashboardRegexMap {
+ return &DashboardRegexMap{
+ Type: DashboardMappingTypeRegex,
+ Options: *NewDashboardV2alpha2RegexMapOptions(),
+ }
+}
+
+// Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.
+// See SpecialValueMatch to see the list of special values.
+// For example, you can configure a special value mapping so that null values appear as N/A.
+// +k8s:openapi-gen=true
+type DashboardSpecialValueMap struct {
+ Type DashboardMappingType `json:"type"`
+ Options DashboardV2alpha2SpecialValueMapOptions `json:"options"`
+}
+
+// NewDashboardSpecialValueMap creates a new DashboardSpecialValueMap object.
+func NewDashboardSpecialValueMap() *DashboardSpecialValueMap {
+ return &DashboardSpecialValueMap{
+ Type: DashboardMappingTypeSpecial,
+ Options: *NewDashboardV2alpha2SpecialValueMapOptions(),
+ }
+}
+
+// Special value types supported by the `SpecialValueMap`
+// +k8s:openapi-gen=true
+type DashboardSpecialValueMatch string
+
+const (
+ DashboardSpecialValueMatchTrue DashboardSpecialValueMatch = "true"
+ DashboardSpecialValueMatchFalse DashboardSpecialValueMatch = "false"
+ DashboardSpecialValueMatchNull DashboardSpecialValueMatch = "null"
+ DashboardSpecialValueMatchNaN DashboardSpecialValueMatch = "nan"
+ DashboardSpecialValueMatchNullAndNaN DashboardSpecialValueMatch = "null+nan"
+ DashboardSpecialValueMatchEmpty DashboardSpecialValueMatch = "empty"
+)
+
+// +k8s:openapi-gen=true
+type DashboardThresholdsConfig struct {
+ Mode DashboardThresholdsMode `json:"mode"`
+ Steps []DashboardThreshold `json:"steps"`
+}
+
+// NewDashboardThresholdsConfig creates a new DashboardThresholdsConfig object.
+func NewDashboardThresholdsConfig() *DashboardThresholdsConfig {
+ return &DashboardThresholdsConfig{
+ Steps: []DashboardThreshold{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardThresholdsMode string
+
+const (
+ DashboardThresholdsModeAbsolute DashboardThresholdsMode = "absolute"
+ DashboardThresholdsModePercentage DashboardThresholdsMode = "percentage"
+)
+
+// +k8s:openapi-gen=true
+type DashboardThreshold struct {
+ Value float64 `json:"value"`
+ Color string `json:"color"`
+}
+
+// NewDashboardThreshold creates a new DashboardThreshold object.
+func NewDashboardThreshold() *DashboardThreshold {
+ return &DashboardThreshold{}
+}
+
+// Map a field to a color.
+// +k8s:openapi-gen=true
+type DashboardFieldColor struct {
+ // The main color scheme mode.
+ Mode DashboardFieldColorModeId `json:"mode"`
+ // The fixed color value for fixed or shades color modes.
+ FixedColor *string `json:"fixedColor,omitempty"`
+ // Some visualizations need to know how to assign a series color from by value color schemes.
+ SeriesBy *DashboardFieldColorSeriesByMode `json:"seriesBy,omitempty"`
+}
+
+// NewDashboardFieldColor creates a new DashboardFieldColor object.
+func NewDashboardFieldColor() *DashboardFieldColor {
+ return &DashboardFieldColor{}
+}
+
+// Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
+// Continuous color interpolates a color using the percentage of a value relative to min and max.
+// Accepted values are:
+// `thresholds`: From thresholds. Informs Grafana to take the color from the matching threshold
+// `palette-classic`: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations
+// `palette-classic-by-name`: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations
+// `continuous-GrYlRd`: ontinuous Green-Yellow-Red palette mode
+// `continuous-RdYlGr`: Continuous Red-Yellow-Green palette mode
+// `continuous-BlYlRd`: Continuous Blue-Yellow-Red palette mode
+// `continuous-YlRd`: Continuous Yellow-Red palette mode
+// `continuous-BlPu`: Continuous Blue-Purple palette mode
+// `continuous-YlBl`: Continuous Yellow-Blue palette mode
+// `continuous-blues`: Continuous Blue palette mode
+// `continuous-reds`: Continuous Red palette mode
+// `continuous-greens`: Continuous Green palette mode
+// `continuous-purples`: Continuous Purple palette mode
+// `shades`: Shades of a single color. Specify a single color, useful in an override rule.
+// `fixed`: Fixed color mode. Specify a single color, useful in an override rule.
+// +k8s:openapi-gen=true
+type DashboardFieldColorModeId string
+
+const (
+ DashboardFieldColorModeIdThresholds DashboardFieldColorModeId = "thresholds"
+ DashboardFieldColorModeIdPaletteClassic DashboardFieldColorModeId = "palette-classic"
+ DashboardFieldColorModeIdPaletteClassicByName DashboardFieldColorModeId = "palette-classic-by-name"
+ DashboardFieldColorModeIdContinuousGrYlRd DashboardFieldColorModeId = "continuous-GrYlRd"
+ DashboardFieldColorModeIdContinuousRdYlGr DashboardFieldColorModeId = "continuous-RdYlGr"
+ DashboardFieldColorModeIdContinuousBlYlRd DashboardFieldColorModeId = "continuous-BlYlRd"
+ DashboardFieldColorModeIdContinuousYlRd DashboardFieldColorModeId = "continuous-YlRd"
+ DashboardFieldColorModeIdContinuousBlPu DashboardFieldColorModeId = "continuous-BlPu"
+ DashboardFieldColorModeIdContinuousYlBl DashboardFieldColorModeId = "continuous-YlBl"
+ DashboardFieldColorModeIdContinuousBlues DashboardFieldColorModeId = "continuous-blues"
+ DashboardFieldColorModeIdContinuousReds DashboardFieldColorModeId = "continuous-reds"
+ DashboardFieldColorModeIdContinuousGreens DashboardFieldColorModeId = "continuous-greens"
+ DashboardFieldColorModeIdContinuousPurples DashboardFieldColorModeId = "continuous-purples"
+ DashboardFieldColorModeIdFixed DashboardFieldColorModeId = "fixed"
+ DashboardFieldColorModeIdShades DashboardFieldColorModeId = "shades"
+)
+
+// Defines how to assign a series color from "by value" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.
+// +k8s:openapi-gen=true
+type DashboardFieldColorSeriesByMode string
+
+const (
+ DashboardFieldColorSeriesByModeMin DashboardFieldColorSeriesByMode = "min"
+ DashboardFieldColorSeriesByModeMax DashboardFieldColorSeriesByMode = "max"
+ DashboardFieldColorSeriesByModeLast DashboardFieldColorSeriesByMode = "last"
+)
+
+// +k8s:openapi-gen=true
+type DashboardDynamicConfigValue struct {
+ Id string `json:"id"`
+ Value interface{} `json:"value,omitempty"`
+}
+
+// NewDashboardDynamicConfigValue creates a new DashboardDynamicConfigValue object.
+func NewDashboardDynamicConfigValue() *DashboardDynamicConfigValue {
+ return &DashboardDynamicConfigValue{
+ Id: "",
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardLibraryPanelKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardLibraryPanelKindSpec `json:"spec"`
+}
+
+// NewDashboardLibraryPanelKind creates a new DashboardLibraryPanelKind object.
+func NewDashboardLibraryPanelKind() *DashboardLibraryPanelKind {
+ return &DashboardLibraryPanelKind{
+ Kind: "LibraryPanel",
+ Spec: *NewDashboardLibraryPanelKindSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardLibraryPanelKindSpec struct {
+ // Panel ID for the library panel in the dashboard
+ Id float64 `json:"id"`
+ // Title for the library panel in the dashboard
+ Title string `json:"title"`
+ LibraryPanel DashboardLibraryPanelRef `json:"libraryPanel"`
+}
+
+// NewDashboardLibraryPanelKindSpec creates a new DashboardLibraryPanelKindSpec object.
+func NewDashboardLibraryPanelKindSpec() *DashboardLibraryPanelKindSpec {
+ return &DashboardLibraryPanelKindSpec{
+ LibraryPanel: *NewDashboardLibraryPanelRef(),
+ }
+}
+
+// A library panel is a reusable panel that you can use in any dashboard.
+// When you make a change to a library panel, that change propagates to all instances of where the panel is used.
+// Library panels streamline reuse of panels across multiple dashboards.
+// +k8s:openapi-gen=true
+type DashboardLibraryPanelRef struct {
+ // Library panel name
+ Name string `json:"name"`
+ // Library panel uid
+ Uid string `json:"uid"`
+}
+
+// NewDashboardLibraryPanelRef creates a new DashboardLibraryPanelRef object.
+func NewDashboardLibraryPanelRef() *DashboardLibraryPanelRef {
+ return &DashboardLibraryPanelRef{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardGridLayoutSpec `json:"spec"`
+}
+
+// NewDashboardGridLayoutKind creates a new DashboardGridLayoutKind object.
+func NewDashboardGridLayoutKind() *DashboardGridLayoutKind {
+ return &DashboardGridLayoutKind{
+ Kind: "GridLayout",
+ Spec: *NewDashboardGridLayoutSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutSpec struct {
+ Items []DashboardGridLayoutItemKind `json:"items"`
+}
+
+// NewDashboardGridLayoutSpec creates a new DashboardGridLayoutSpec object.
+func NewDashboardGridLayoutSpec() *DashboardGridLayoutSpec {
+ return &DashboardGridLayoutSpec{
+ Items: []DashboardGridLayoutItemKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutItemKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardGridLayoutItemSpec `json:"spec"`
+}
+
+// NewDashboardGridLayoutItemKind creates a new DashboardGridLayoutItemKind object.
+func NewDashboardGridLayoutItemKind() *DashboardGridLayoutItemKind {
+ return &DashboardGridLayoutItemKind{
+ Kind: "GridLayoutItem",
+ Spec: *NewDashboardGridLayoutItemSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutItemSpec struct {
+ X int64 `json:"x"`
+ Y int64 `json:"y"`
+ Width int64 `json:"width"`
+ Height int64 `json:"height"`
+ // reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference
+ Element DashboardElementReference `json:"element"`
+ Repeat *DashboardRepeatOptions `json:"repeat,omitempty"`
+}
+
+// NewDashboardGridLayoutItemSpec creates a new DashboardGridLayoutItemSpec object.
+func NewDashboardGridLayoutItemSpec() *DashboardGridLayoutItemSpec {
+ return &DashboardGridLayoutItemSpec{
+ Element: *NewDashboardElementReference(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardElementReference struct {
+ Kind string `json:"kind"`
+ Name string `json:"name"`
+}
+
+// NewDashboardElementReference creates a new DashboardElementReference object.
+func NewDashboardElementReference() *DashboardElementReference {
+ return &DashboardElementReference{
+ Kind: "ElementReference",
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardRepeatOptions struct {
+ Mode string `json:"mode"`
+ Value string `json:"value"`
+ Direction *DashboardRepeatOptionsDirection `json:"direction,omitempty"`
+ MaxPerRow *int64 `json:"maxPerRow,omitempty"`
+}
+
+// NewDashboardRepeatOptions creates a new DashboardRepeatOptions object.
+func NewDashboardRepeatOptions() *DashboardRepeatOptions {
+ return &DashboardRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
+}
+
+// other repeat modes will be added in the future: label, frame
+// +k8s:openapi-gen=true
+const DashboardRepeatMode = "variable"
+
+// +k8s:openapi-gen=true
+type DashboardRowsLayoutKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardRowsLayoutSpec `json:"spec"`
+}
+
+// NewDashboardRowsLayoutKind creates a new DashboardRowsLayoutKind object.
+func NewDashboardRowsLayoutKind() *DashboardRowsLayoutKind {
+ return &DashboardRowsLayoutKind{
+ Kind: "RowsLayout",
+ Spec: *NewDashboardRowsLayoutSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardRowsLayoutSpec struct {
+ Rows []DashboardRowsLayoutRowKind `json:"rows"`
+}
+
+// NewDashboardRowsLayoutSpec creates a new DashboardRowsLayoutSpec object.
+func NewDashboardRowsLayoutSpec() *DashboardRowsLayoutSpec {
+ return &DashboardRowsLayoutSpec{
+ Rows: []DashboardRowsLayoutRowKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardRowsLayoutRowKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardRowsLayoutRowSpec `json:"spec"`
+}
+
+// NewDashboardRowsLayoutRowKind creates a new DashboardRowsLayoutRowKind object.
+func NewDashboardRowsLayoutRowKind() *DashboardRowsLayoutRowKind {
+ return &DashboardRowsLayoutRowKind{
+ Kind: "RowsLayoutRow",
+ Spec: *NewDashboardRowsLayoutRowSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardRowsLayoutRowSpec struct {
+ Title *string `json:"title,omitempty"`
+ Collapse *bool `json:"collapse,omitempty"`
+ HideHeader *bool `json:"hideHeader,omitempty"`
+ FillScreen *bool `json:"fillScreen,omitempty"`
+ ConditionalRendering *DashboardConditionalRenderingGroupKind `json:"conditionalRendering,omitempty"`
+ Repeat *DashboardRowRepeatOptions `json:"repeat,omitempty"`
+ Layout DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind `json:"layout"`
+}
+
+// NewDashboardRowsLayoutRowSpec creates a new DashboardRowsLayoutRowSpec object.
+func NewDashboardRowsLayoutRowSpec() *DashboardRowsLayoutRowSpec {
+ return &DashboardRowsLayoutRowSpec{
+ Layout: *NewDashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingGroupKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardConditionalRenderingGroupSpec `json:"spec"`
+}
+
+// NewDashboardConditionalRenderingGroupKind creates a new DashboardConditionalRenderingGroupKind object.
+func NewDashboardConditionalRenderingGroupKind() *DashboardConditionalRenderingGroupKind {
+ return &DashboardConditionalRenderingGroupKind{
+ Kind: "ConditionalRenderingGroup",
+ Spec: *NewDashboardConditionalRenderingGroupSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingGroupSpec struct {
+ Visibility DashboardConditionalRenderingGroupSpecVisibility `json:"visibility"`
+ Condition DashboardConditionalRenderingGroupSpecCondition `json:"condition"`
+ Items []DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind `json:"items"`
+}
+
+// NewDashboardConditionalRenderingGroupSpec creates a new DashboardConditionalRenderingGroupSpec object.
+func NewDashboardConditionalRenderingGroupSpec() *DashboardConditionalRenderingGroupSpec {
+ return &DashboardConditionalRenderingGroupSpec{
+ Items: []DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardConditionalRenderingVariableSpec `json:"spec"`
+}
+
+// NewDashboardConditionalRenderingVariableKind creates a new DashboardConditionalRenderingVariableKind object.
+func NewDashboardConditionalRenderingVariableKind() *DashboardConditionalRenderingVariableKind {
+ return &DashboardConditionalRenderingVariableKind{
+ Kind: "ConditionalRenderingVariable",
+ Spec: *NewDashboardConditionalRenderingVariableSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingVariableSpec struct {
+ Variable string `json:"variable"`
+ Operator DashboardConditionalRenderingVariableSpecOperator `json:"operator"`
+ Value string `json:"value"`
+}
+
+// NewDashboardConditionalRenderingVariableSpec creates a new DashboardConditionalRenderingVariableSpec object.
+func NewDashboardConditionalRenderingVariableSpec() *DashboardConditionalRenderingVariableSpec {
+ return &DashboardConditionalRenderingVariableSpec{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingDataKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardConditionalRenderingDataSpec `json:"spec"`
+}
+
+// NewDashboardConditionalRenderingDataKind creates a new DashboardConditionalRenderingDataKind object.
+func NewDashboardConditionalRenderingDataKind() *DashboardConditionalRenderingDataKind {
+ return &DashboardConditionalRenderingDataKind{
+ Kind: "ConditionalRenderingData",
+ Spec: *NewDashboardConditionalRenderingDataSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingDataSpec struct {
+ Value bool `json:"value"`
+}
+
+// NewDashboardConditionalRenderingDataSpec creates a new DashboardConditionalRenderingDataSpec object.
+func NewDashboardConditionalRenderingDataSpec() *DashboardConditionalRenderingDataSpec {
+ return &DashboardConditionalRenderingDataSpec{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingTimeRangeSizeKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardConditionalRenderingTimeRangeSizeSpec `json:"spec"`
+}
+
+// NewDashboardConditionalRenderingTimeRangeSizeKind creates a new DashboardConditionalRenderingTimeRangeSizeKind object.
+func NewDashboardConditionalRenderingTimeRangeSizeKind() *DashboardConditionalRenderingTimeRangeSizeKind {
+ return &DashboardConditionalRenderingTimeRangeSizeKind{
+ Kind: "ConditionalRenderingTimeRangeSize",
+ Spec: *NewDashboardConditionalRenderingTimeRangeSizeSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingTimeRangeSizeSpec struct {
+ Value string `json:"value"`
+}
+
+// NewDashboardConditionalRenderingTimeRangeSizeSpec creates a new DashboardConditionalRenderingTimeRangeSizeSpec object.
+func NewDashboardConditionalRenderingTimeRangeSizeSpec() *DashboardConditionalRenderingTimeRangeSizeSpec {
+ return &DashboardConditionalRenderingTimeRangeSizeSpec{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardRowRepeatOptions struct {
+ Mode string `json:"mode"`
+ Value string `json:"value"`
+}
+
+// NewDashboardRowRepeatOptions creates a new DashboardRowRepeatOptions object.
+func NewDashboardRowRepeatOptions() *DashboardRowRepeatOptions {
+ return &DashboardRowRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardAutoGridLayoutSpec `json:"spec"`
+}
+
+// NewDashboardAutoGridLayoutKind creates a new DashboardAutoGridLayoutKind object.
+func NewDashboardAutoGridLayoutKind() *DashboardAutoGridLayoutKind {
+ return &DashboardAutoGridLayoutKind{
+ Kind: "AutoGridLayout",
+ Spec: *NewDashboardAutoGridLayoutSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutSpec struct {
+ MaxColumnCount *float64 `json:"maxColumnCount,omitempty"`
+ ColumnWidthMode DashboardAutoGridLayoutSpecColumnWidthMode `json:"columnWidthMode"`
+ ColumnWidth *float64 `json:"columnWidth,omitempty"`
+ RowHeightMode DashboardAutoGridLayoutSpecRowHeightMode `json:"rowHeightMode"`
+ RowHeight *float64 `json:"rowHeight,omitempty"`
+ FillScreen *bool `json:"fillScreen,omitempty"`
+ Items []DashboardAutoGridLayoutItemKind `json:"items"`
+}
+
+// NewDashboardAutoGridLayoutSpec creates a new DashboardAutoGridLayoutSpec object.
+func NewDashboardAutoGridLayoutSpec() *DashboardAutoGridLayoutSpec {
+ return &DashboardAutoGridLayoutSpec{
+ MaxColumnCount: (func(input float64) *float64 { return &input })(3),
+ FillScreen: (func(input bool) *bool { return &input })(false),
+ Items: []DashboardAutoGridLayoutItemKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutItemKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardAutoGridLayoutItemSpec `json:"spec"`
+}
+
+// NewDashboardAutoGridLayoutItemKind creates a new DashboardAutoGridLayoutItemKind object.
+func NewDashboardAutoGridLayoutItemKind() *DashboardAutoGridLayoutItemKind {
+ return &DashboardAutoGridLayoutItemKind{
+ Kind: "AutoGridLayoutItem",
+ Spec: *NewDashboardAutoGridLayoutItemSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutItemSpec struct {
+ Element DashboardElementReference `json:"element"`
+ Repeat *DashboardAutoGridRepeatOptions `json:"repeat,omitempty"`
+ ConditionalRendering *DashboardConditionalRenderingGroupKind `json:"conditionalRendering,omitempty"`
+}
+
+// NewDashboardAutoGridLayoutItemSpec creates a new DashboardAutoGridLayoutItemSpec object.
+func NewDashboardAutoGridLayoutItemSpec() *DashboardAutoGridLayoutItemSpec {
+ return &DashboardAutoGridLayoutItemSpec{
+ Element: *NewDashboardElementReference(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridRepeatOptions struct {
+ Mode string `json:"mode"`
+ Value string `json:"value"`
+}
+
+// NewDashboardAutoGridRepeatOptions creates a new DashboardAutoGridRepeatOptions object.
+func NewDashboardAutoGridRepeatOptions() *DashboardAutoGridRepeatOptions {
+ return &DashboardAutoGridRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTabsLayoutKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardTabsLayoutSpec `json:"spec"`
+}
+
+// NewDashboardTabsLayoutKind creates a new DashboardTabsLayoutKind object.
+func NewDashboardTabsLayoutKind() *DashboardTabsLayoutKind {
+ return &DashboardTabsLayoutKind{
+ Kind: "TabsLayout",
+ Spec: *NewDashboardTabsLayoutSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTabsLayoutSpec struct {
+ Tabs []DashboardTabsLayoutTabKind `json:"tabs"`
+}
+
+// NewDashboardTabsLayoutSpec creates a new DashboardTabsLayoutSpec object.
+func NewDashboardTabsLayoutSpec() *DashboardTabsLayoutSpec {
+ return &DashboardTabsLayoutSpec{
+ Tabs: []DashboardTabsLayoutTabKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTabsLayoutTabKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardTabsLayoutTabSpec `json:"spec"`
+}
+
+// NewDashboardTabsLayoutTabKind creates a new DashboardTabsLayoutTabKind object.
+func NewDashboardTabsLayoutTabKind() *DashboardTabsLayoutTabKind {
+ return &DashboardTabsLayoutTabKind{
+ Kind: "TabsLayoutTab",
+ Spec: *NewDashboardTabsLayoutTabSpec(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTabsLayoutTabSpec struct {
+ Title *string `json:"title,omitempty"`
+ Layout DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind `json:"layout"`
+ ConditionalRendering *DashboardConditionalRenderingGroupKind `json:"conditionalRendering,omitempty"`
+ Repeat *DashboardTabRepeatOptions `json:"repeat,omitempty"`
+}
+
+// NewDashboardTabsLayoutTabSpec creates a new DashboardTabsLayoutTabSpec object.
+func NewDashboardTabsLayoutTabSpec() *DashboardTabsLayoutTabSpec {
+ return &DashboardTabsLayoutTabSpec{
+ Layout: *NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTabRepeatOptions struct {
+ Mode string `json:"mode"`
+ Value string `json:"value"`
+}
+
+// NewDashboardTabRepeatOptions creates a new DashboardTabRepeatOptions object.
+func NewDashboardTabRepeatOptions() *DashboardTabRepeatOptions {
+ return &DashboardTabRepeatOptions{
+ Mode: DashboardRepeatMode,
+ }
+}
+
+// Links with references to other dashboards or external resources
+// +k8s:openapi-gen=true
+type DashboardDashboardLink struct {
+ // Title to display with the link
+ Title string `json:"title"`
+ // Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+ // FIXME: The type is generated as `type: DashboardLinkType | dashboardLinkType.Link;` but it should be `type: DashboardLinkType`
+ Type DashboardDashboardLinkType `json:"type"`
+ // Icon name to be displayed with the link
+ Icon string `json:"icon"`
+ // Tooltip to display when the user hovers their mouse over it
+ Tooltip string `json:"tooltip"`
+ // Link URL. Only required/valid if the type is link
+ Url *string `json:"url,omitempty"`
+ // List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards
+ Tags []string `json:"tags"`
+ // If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards
+ AsDropdown bool `json:"asDropdown"`
+ // If true, the link will be opened in a new tab
+ TargetBlank bool `json:"targetBlank"`
+ // If true, includes current template variables values in the link as query params
+ IncludeVars bool `json:"includeVars"`
+ // If true, includes current time range in the link as query params
+ KeepTime bool `json:"keepTime"`
+}
+
+// NewDashboardDashboardLink creates a new DashboardDashboardLink object.
+func NewDashboardDashboardLink() *DashboardDashboardLink {
+ return &DashboardDashboardLink{
+ Tags: []string{},
+ AsDropdown: false,
+ TargetBlank: false,
+ IncludeVars: false,
+ KeepTime: false,
+ }
+}
+
+// Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+// +k8s:openapi-gen=true
+type DashboardDashboardLinkType string
+
+const (
+ DashboardDashboardLinkTypeLink DashboardDashboardLinkType = "link"
+ DashboardDashboardLinkTypeDashboards DashboardDashboardLinkType = "dashboards"
+)
+
+// Time configuration
+// It defines the default time config for the time picker, the refresh picker for the specific dashboard.
+// +k8s:openapi-gen=true
+type DashboardTimeSettingsSpec struct {
+ // Timezone of dashboard. Accepted values are IANA TZDB zone ID or "browser" or "utc".
+ Timezone *string `json:"timezone,omitempty"`
+ // Start time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ From string `json:"from"`
+ // End time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ To string `json:"to"`
+ // Refresh rate of dashboard. Represented via interval string, e.g. "5s", "1m", "1h", "1d".
+ // v1: refresh
+ AutoRefresh string `json:"autoRefresh"`
+ // Interval options available in the refresh picker dropdown.
+ // v1: timepicker.refresh_intervals
+ AutoRefreshIntervals []string `json:"autoRefreshIntervals"`
+ // Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
+ // v1: timepicker.quick_ranges , not exposed in the UI
+ QuickRanges []DashboardTimeRangeOption `json:"quickRanges,omitempty"`
+ // Whether timepicker is visible or not.
+ // v1: timepicker.hidden
+ HideTimepicker bool `json:"hideTimepicker"`
+ // Day when the week starts. Expressed by the name of the day in lowercase, e.g. "monday".
+ WeekStart *DashboardTimeSettingsSpecWeekStart `json:"weekStart,omitempty"`
+ // The month that the fiscal year starts on. 0 = January, 11 = December
+ FiscalYearStartMonth int64 `json:"fiscalYearStartMonth"`
+ // Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
+ // v1: timepicker.nowDelay
+ NowDelay *string `json:"nowDelay,omitempty"`
+}
+
+// NewDashboardTimeSettingsSpec creates a new DashboardTimeSettingsSpec object.
+func NewDashboardTimeSettingsSpec() *DashboardTimeSettingsSpec {
+ return &DashboardTimeSettingsSpec{
+ Timezone: (func(input string) *string { return &input })("browser"),
+ From: "now-6h",
+ To: "now",
+ AutoRefresh: "",
+ AutoRefreshIntervals: []string{"5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"},
+ HideTimepicker: false,
+ FiscalYearStartMonth: 0,
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardTimeRangeOption struct {
+ Display string `json:"display"`
+ From string `json:"from"`
+ To string `json:"to"`
+}
+
+// NewDashboardTimeRangeOption creates a new DashboardTimeRangeOption object.
+func NewDashboardTimeRangeOption() *DashboardTimeRangeOption {
+ return &DashboardTimeRangeOption{
+ Display: "Last 6 hours",
+ From: "now-6h",
+ To: "now",
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardVariableKind = DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind
+
+// NewDashboardVariableKind creates a new DashboardVariableKind object.
+func NewDashboardVariableKind() *DashboardVariableKind {
+ return NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind()
+}
+
+// Query variable kind
+// +k8s:openapi-gen=true
+type DashboardQueryVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardQueryVariableSpec `json:"spec"`
+}
+
+// NewDashboardQueryVariableKind creates a new DashboardQueryVariableKind object.
+func NewDashboardQueryVariableKind() *DashboardQueryVariableKind {
+ return &DashboardQueryVariableKind{
+ Kind: "QueryVariable",
+ Spec: *NewDashboardQueryVariableSpec(),
+ }
+}
+
+// Query variable specification
+// +k8s:openapi-gen=true
+type DashboardQueryVariableSpec struct {
+ Name string `json:"name"`
+ Current DashboardVariableOption `json:"current"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ Refresh DashboardVariableRefresh `json:"refresh"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ Query DashboardDataQueryKind `json:"query"`
+ Regex string `json:"regex"`
+ Sort DashboardVariableSort `json:"sort"`
+ Definition *string `json:"definition,omitempty"`
+ Options []DashboardVariableOption `json:"options"`
+ Multi bool `json:"multi"`
+ IncludeAll bool `json:"includeAll"`
+ AllValue *string `json:"allValue,omitempty"`
+ Placeholder *string `json:"placeholder,omitempty"`
+ AllowCustomValue bool `json:"allowCustomValue"`
+ StaticOptions []DashboardVariableOption `json:"staticOptions,omitempty"`
+ StaticOptionsOrder *DashboardQueryVariableSpecStaticOptionsOrder `json:"staticOptionsOrder,omitempty"`
+}
+
+// NewDashboardQueryVariableSpec creates a new DashboardQueryVariableSpec object.
+func NewDashboardQueryVariableSpec() *DashboardQueryVariableSpec {
+ return &DashboardQueryVariableSpec{
+ Name: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Hide: DashboardVariableHideDontHide,
+ Refresh: DashboardVariableRefreshNever,
+ SkipUrlSync: false,
+ Query: *NewDashboardDataQueryKind(),
+ Regex: "",
+ Options: []DashboardVariableOption{},
+ Multi: false,
+ IncludeAll: false,
+ AllowCustomValue: true,
+ }
+}
+
+// Variable option specification
+// +k8s:openapi-gen=true
+type DashboardVariableOption struct {
+ // Whether the option is selected or not
+ Selected *bool `json:"selected,omitempty"`
+ // Text to be displayed for the option
+ Text DashboardStringOrArrayOfString `json:"text"`
+ // Value of the option
+ Value DashboardStringOrArrayOfString `json:"value"`
+}
+
+// NewDashboardVariableOption creates a new DashboardVariableOption object.
+func NewDashboardVariableOption() *DashboardVariableOption {
+ return &DashboardVariableOption{
+ Text: *NewDashboardStringOrArrayOfString(),
+ Value: *NewDashboardStringOrArrayOfString(),
+ }
+}
+
+// Determine if the variable shows on dashboard
+// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
+// +k8s:openapi-gen=true
+type DashboardVariableHide string
+
+const (
+ DashboardVariableHideDontHide DashboardVariableHide = "dontHide"
+ DashboardVariableHideHideLabel DashboardVariableHide = "hideLabel"
+ DashboardVariableHideHideVariable DashboardVariableHide = "hideVariable"
+)
+
+// Options to config when to refresh a variable
+// `never`: Never refresh the variable
+// `onDashboardLoad`: Queries the data source every time the dashboard loads.
+// `onTimeRangeChanged`: Queries the data source when the dashboard time range changes.
+// +k8s:openapi-gen=true
+type DashboardVariableRefresh string
+
+const (
+ DashboardVariableRefreshNever DashboardVariableRefresh = "never"
+ DashboardVariableRefreshOnDashboardLoad DashboardVariableRefresh = "onDashboardLoad"
+ DashboardVariableRefreshOnTimeRangeChanged DashboardVariableRefresh = "onTimeRangeChanged"
+)
+
+// Sort variable options
+// Accepted values are:
+// `disabled`: No sorting
+// `alphabeticalAsc`: Alphabetical ASC
+// `alphabeticalDesc`: Alphabetical DESC
+// `numericalAsc`: Numerical ASC
+// `numericalDesc`: Numerical DESC
+// `alphabeticalCaseInsensitiveAsc`: Alphabetical Case Insensitive ASC
+// `alphabeticalCaseInsensitiveDesc`: Alphabetical Case Insensitive DESC
+// `naturalAsc`: Natural ASC
+// `naturalDesc`: Natural DESC
+// VariableSort enum with default value
+// +k8s:openapi-gen=true
+type DashboardVariableSort string
+
+const (
+ DashboardVariableSortDisabled DashboardVariableSort = "disabled"
+ DashboardVariableSortAlphabeticalAsc DashboardVariableSort = "alphabeticalAsc"
+ DashboardVariableSortAlphabeticalDesc DashboardVariableSort = "alphabeticalDesc"
+ DashboardVariableSortNumericalAsc DashboardVariableSort = "numericalAsc"
+ DashboardVariableSortNumericalDesc DashboardVariableSort = "numericalDesc"
+ DashboardVariableSortAlphabeticalCaseInsensitiveAsc DashboardVariableSort = "alphabeticalCaseInsensitiveAsc"
+ DashboardVariableSortAlphabeticalCaseInsensitiveDesc DashboardVariableSort = "alphabeticalCaseInsensitiveDesc"
+ DashboardVariableSortNaturalAsc DashboardVariableSort = "naturalAsc"
+ DashboardVariableSortNaturalDesc DashboardVariableSort = "naturalDesc"
+)
+
+// Text variable kind
+// +k8s:openapi-gen=true
+type DashboardTextVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardTextVariableSpec `json:"spec"`
+}
+
+// NewDashboardTextVariableKind creates a new DashboardTextVariableKind object.
+func NewDashboardTextVariableKind() *DashboardTextVariableKind {
+ return &DashboardTextVariableKind{
+ Kind: "TextVariable",
+ Spec: *NewDashboardTextVariableSpec(),
+ }
+}
+
+// Text variable specification
+// +k8s:openapi-gen=true
+type DashboardTextVariableSpec struct {
+ Name string `json:"name"`
+ Current DashboardVariableOption `json:"current"`
+ Query string `json:"query"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+}
+
+// NewDashboardTextVariableSpec creates a new DashboardTextVariableSpec object.
+func NewDashboardTextVariableSpec() *DashboardTextVariableSpec {
+ return &DashboardTextVariableSpec{
+ Name: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Query: "",
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ }
+}
+
+// Constant variable kind
+// +k8s:openapi-gen=true
+type DashboardConstantVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardConstantVariableSpec `json:"spec"`
+}
+
+// NewDashboardConstantVariableKind creates a new DashboardConstantVariableKind object.
+func NewDashboardConstantVariableKind() *DashboardConstantVariableKind {
+ return &DashboardConstantVariableKind{
+ Kind: "ConstantVariable",
+ Spec: *NewDashboardConstantVariableSpec(),
+ }
+}
+
+// Constant variable specification
+// +k8s:openapi-gen=true
+type DashboardConstantVariableSpec struct {
+ Name string `json:"name"`
+ Query string `json:"query"`
+ Current DashboardVariableOption `json:"current"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+}
+
+// NewDashboardConstantVariableSpec creates a new DashboardConstantVariableSpec object.
+func NewDashboardConstantVariableSpec() *DashboardConstantVariableSpec {
+ return &DashboardConstantVariableSpec{
+ Name: "",
+ Query: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ }
+}
+
+// Datasource variable kind
+// +k8s:openapi-gen=true
+type DashboardDatasourceVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardDatasourceVariableSpec `json:"spec"`
+}
+
+// NewDashboardDatasourceVariableKind creates a new DashboardDatasourceVariableKind object.
+func NewDashboardDatasourceVariableKind() *DashboardDatasourceVariableKind {
+ return &DashboardDatasourceVariableKind{
+ Kind: "DatasourceVariable",
+ Spec: *NewDashboardDatasourceVariableSpec(),
+ }
+}
+
+// Datasource variable specification
+// +k8s:openapi-gen=true
+type DashboardDatasourceVariableSpec struct {
+ Name string `json:"name"`
+ PluginId string `json:"pluginId"`
+ Refresh DashboardVariableRefresh `json:"refresh"`
+ Regex string `json:"regex"`
+ Current DashboardVariableOption `json:"current"`
+ Options []DashboardVariableOption `json:"options"`
+ Multi bool `json:"multi"`
+ IncludeAll bool `json:"includeAll"`
+ AllValue *string `json:"allValue,omitempty"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+ AllowCustomValue bool `json:"allowCustomValue"`
+}
+
+// NewDashboardDatasourceVariableSpec creates a new DashboardDatasourceVariableSpec object.
+func NewDashboardDatasourceVariableSpec() *DashboardDatasourceVariableSpec {
+ return &DashboardDatasourceVariableSpec{
+ Name: "",
+ PluginId: "",
+ Refresh: DashboardVariableRefreshNever,
+ Regex: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Options: []DashboardVariableOption{},
+ Multi: false,
+ IncludeAll: false,
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ AllowCustomValue: true,
+ }
+}
+
+// Interval variable kind
+// +k8s:openapi-gen=true
+type DashboardIntervalVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardIntervalVariableSpec `json:"spec"`
+}
+
+// NewDashboardIntervalVariableKind creates a new DashboardIntervalVariableKind object.
+func NewDashboardIntervalVariableKind() *DashboardIntervalVariableKind {
+ return &DashboardIntervalVariableKind{
+ Kind: "IntervalVariable",
+ Spec: *NewDashboardIntervalVariableSpec(),
+ }
+}
+
+// Interval variable specification
+// +k8s:openapi-gen=true
+type DashboardIntervalVariableSpec struct {
+ Name string `json:"name"`
+ Query string `json:"query"`
+ Current DashboardVariableOption `json:"current"`
+ Options []DashboardVariableOption `json:"options"`
+ Auto bool `json:"auto"`
+ AutoMin string `json:"auto_min"`
+ AutoCount int64 `json:"auto_count"`
+ Refresh DashboardVariableRefresh `json:"refresh"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+}
+
+// NewDashboardIntervalVariableSpec creates a new DashboardIntervalVariableSpec object.
+func NewDashboardIntervalVariableSpec() *DashboardIntervalVariableSpec {
+ return &DashboardIntervalVariableSpec{
+ Name: "",
+ Query: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Options: []DashboardVariableOption{},
+ Auto: false,
+ AutoMin: "",
+ AutoCount: 0,
+ Refresh: DashboardVariableRefreshNever,
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ }
+}
+
+// Custom variable kind
+// +k8s:openapi-gen=true
+type DashboardCustomVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardCustomVariableSpec `json:"spec"`
+}
+
+// NewDashboardCustomVariableKind creates a new DashboardCustomVariableKind object.
+func NewDashboardCustomVariableKind() *DashboardCustomVariableKind {
+ return &DashboardCustomVariableKind{
+ Kind: "CustomVariable",
+ Spec: *NewDashboardCustomVariableSpec(),
+ }
+}
+
+// Custom variable specification
+// +k8s:openapi-gen=true
+type DashboardCustomVariableSpec struct {
+ Name string `json:"name"`
+ Query string `json:"query"`
+ Current DashboardVariableOption `json:"current"`
+ Options []DashboardVariableOption `json:"options"`
+ Multi bool `json:"multi"`
+ IncludeAll bool `json:"includeAll"`
+ AllValue *string `json:"allValue,omitempty"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+ AllowCustomValue bool `json:"allowCustomValue"`
+}
+
+// NewDashboardCustomVariableSpec creates a new DashboardCustomVariableSpec object.
+func NewDashboardCustomVariableSpec() *DashboardCustomVariableSpec {
+ return &DashboardCustomVariableSpec{
+ Name: "",
+ Query: "",
+ Current: *NewDashboardVariableOption(),
+ Options: []DashboardVariableOption{},
+ Multi: false,
+ IncludeAll: false,
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ AllowCustomValue: true,
+ }
+}
+
+// Group variable kind
+// +k8s:openapi-gen=true
+type DashboardGroupByVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardGroupByVariableSpec `json:"spec"`
+}
+
+// NewDashboardGroupByVariableKind creates a new DashboardGroupByVariableKind object.
+func NewDashboardGroupByVariableKind() *DashboardGroupByVariableKind {
+ return &DashboardGroupByVariableKind{
+ Kind: "GroupByVariable",
+ Spec: *NewDashboardGroupByVariableSpec(),
+ }
+}
+
+// GroupBy variable specification
+// +k8s:openapi-gen=true
+type DashboardGroupByVariableSpec struct {
+ Name string `json:"name"`
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ DefaultValue *DashboardVariableOption `json:"defaultValue,omitempty"`
+ Current DashboardVariableOption `json:"current"`
+ Options []DashboardVariableOption `json:"options"`
+ Multi bool `json:"multi"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+}
+
+// NewDashboardGroupByVariableSpec creates a new DashboardGroupByVariableSpec object.
+func NewDashboardGroupByVariableSpec() *DashboardGroupByVariableSpec {
+ return &DashboardGroupByVariableSpec{
+ Name: "",
+ Current: DashboardVariableOption{
+ Text: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ Value: DashboardStringOrArrayOfString{
+ String: (func(input string) *string { return &input })(""),
+ },
+ },
+ Options: []DashboardVariableOption{},
+ Multi: false,
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ }
+}
+
+// Adhoc variable kind
+// +k8s:openapi-gen=true
+type DashboardAdhocVariableKind struct {
+ Kind string `json:"kind"`
+ Spec DashboardAdhocVariableSpec `json:"spec"`
+}
+
+// NewDashboardAdhocVariableKind creates a new DashboardAdhocVariableKind object.
+func NewDashboardAdhocVariableKind() *DashboardAdhocVariableKind {
+ return &DashboardAdhocVariableKind{
+ Kind: "AdhocVariable",
+ Spec: *NewDashboardAdhocVariableSpec(),
+ }
+}
+
+// Adhoc variable specification
+// +k8s:openapi-gen=true
+type DashboardAdhocVariableSpec struct {
+ Name string `json:"name"`
+ Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
+ BaseFilters []DashboardAdHocFilterWithLabels `json:"baseFilters"`
+ Filters []DashboardAdHocFilterWithLabels `json:"filters"`
+ DefaultKeys []DashboardMetricFindValue `json:"defaultKeys"`
+ Label *string `json:"label,omitempty"`
+ Hide DashboardVariableHide `json:"hide"`
+ SkipUrlSync bool `json:"skipUrlSync"`
+ Description *string `json:"description,omitempty"`
+ AllowCustomValue bool `json:"allowCustomValue"`
+}
+
+// NewDashboardAdhocVariableSpec creates a new DashboardAdhocVariableSpec object.
+func NewDashboardAdhocVariableSpec() *DashboardAdhocVariableSpec {
+ return &DashboardAdhocVariableSpec{
+ Name: "",
+ BaseFilters: []DashboardAdHocFilterWithLabels{},
+ Filters: []DashboardAdHocFilterWithLabels{},
+ DefaultKeys: []DashboardMetricFindValue{},
+ Hide: DashboardVariableHideDontHide,
+ SkipUrlSync: false,
+ AllowCustomValue: true,
+ }
+}
+
+// Define the AdHocFilterWithLabels type
+// +k8s:openapi-gen=true
+type DashboardAdHocFilterWithLabels struct {
+ Key string `json:"key"`
+ Operator string `json:"operator"`
+ Value string `json:"value"`
+ Values []string `json:"values,omitempty"`
+ KeyLabel *string `json:"keyLabel,omitempty"`
+ ValueLabels []string `json:"valueLabels,omitempty"`
+ ForceEdit *bool `json:"forceEdit,omitempty"`
+ Origin string `json:"origin,omitempty"`
+ // @deprecated
+ Condition *string `json:"condition,omitempty"`
+}
+
+// NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object.
+func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels {
+ return &DashboardAdHocFilterWithLabels{
+ Origin: DashboardFilterOrigin,
+ }
+}
+
+// Determine the origin of the adhoc variable filter
+// +k8s:openapi-gen=true
+const DashboardFilterOrigin = "dashboard"
+
+// Define the MetricFindValue type
+// +k8s:openapi-gen=true
+type DashboardMetricFindValue struct {
+ Text string `json:"text"`
+ Value *DashboardStringOrFloat64 `json:"value,omitempty"`
+ Group *string `json:"group,omitempty"`
+ Expandable *bool `json:"expandable,omitempty"`
+}
+
+// NewDashboardMetricFindValue creates a new DashboardMetricFindValue object.
+func NewDashboardMetricFindValue() *DashboardMetricFindValue {
+ return &DashboardMetricFindValue{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardSpec struct {
+ Annotations []DashboardAnnotationQueryKind `json:"annotations"`
+ // Configuration of dashboard cursor sync behavior.
+ // "Off" for no shared crosshair or tooltip (default).
+ // "Crosshair" for shared crosshair.
+ // "Tooltip" for shared crosshair AND shared tooltip.
+ CursorSync DashboardDashboardCursorSync `json:"cursorSync"`
+ // Description of dashboard.
+ Description *string `json:"description,omitempty"`
+ // Whether a dashboard is editable or not.
+ Editable *bool `json:"editable,omitempty"`
+ Elements map[string]DashboardElement `json:"elements"`
+ Layout DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind `json:"layout"`
+ // Links with references to other dashboards or external websites.
+ Links []DashboardDashboardLink `json:"links"`
+ // When set to true, the dashboard will redraw panels at an interval matching the pixel width.
+ // This will keep data "moving left" regardless of the query refresh rate. This setting helps
+ // avoid dashboards presenting stale live data.
+ LiveNow *bool `json:"liveNow,omitempty"`
+ // When set to true, the dashboard will load all panels in the dashboard when it's loaded.
+ Preload bool `json:"preload"`
+ // Plugins only. The version of the dashboard installed together with the plugin.
+ // This is used to determine if the dashboard should be updated when the plugin is updated.
+ Revision *uint16 `json:"revision,omitempty"`
+ // Tags associated with dashboard.
+ Tags []string `json:"tags"`
+ TimeSettings DashboardTimeSettingsSpec `json:"timeSettings"`
+ // Title of dashboard.
+ Title string `json:"title"`
+ // Configured template variables.
+ Variables []DashboardVariableKind `json:"variables"`
+}
+
+// NewDashboardSpec creates a new DashboardSpec object.
+func NewDashboardSpec() *DashboardSpec {
+ return &DashboardSpec{
+ Annotations: []DashboardAnnotationQueryKind{},
+ CursorSync: DashboardDashboardCursorSyncOff,
+ Editable: (func(input bool) *bool { return &input })(true),
+ Elements: map[string]DashboardElement{},
+ Layout: *NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(),
+ Links: []DashboardDashboardLink{},
+ Preload: false,
+ Tags: []string{},
+ TimeSettings: *NewDashboardTimeSettingsSpec(),
+ Variables: []DashboardVariableKind{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardV2alpha2FieldConfigSourceOverrides struct {
+ Matcher DashboardMatcherConfig `json:"matcher"`
+ Properties []DashboardDynamicConfigValue `json:"properties"`
+}
+
+// NewDashboardV2alpha2FieldConfigSourceOverrides creates a new DashboardV2alpha2FieldConfigSourceOverrides object.
+func NewDashboardV2alpha2FieldConfigSourceOverrides() *DashboardV2alpha2FieldConfigSourceOverrides {
+ return &DashboardV2alpha2FieldConfigSourceOverrides{
+ Matcher: *NewDashboardMatcherConfig(),
+ Properties: []DashboardDynamicConfigValue{},
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardV2alpha2RangeMapOptions struct {
+ // Min value of the range. It can be null which means -Infinity
+ From *float64 `json:"from"`
+ // Max value of the range. It can be null which means +Infinity
+ To *float64 `json:"to"`
+ // Config to apply when the value is within the range
+ Result DashboardValueMappingResult `json:"result"`
+}
+
+// NewDashboardV2alpha2RangeMapOptions creates a new DashboardV2alpha2RangeMapOptions object.
+func NewDashboardV2alpha2RangeMapOptions() *DashboardV2alpha2RangeMapOptions {
+ return &DashboardV2alpha2RangeMapOptions{
+ Result: *NewDashboardValueMappingResult(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardV2alpha2RegexMapOptions struct {
+ // Regular expression to match against
+ Pattern string `json:"pattern"`
+ // Config to apply when the value matches the regex
+ Result DashboardValueMappingResult `json:"result"`
+}
+
+// NewDashboardV2alpha2RegexMapOptions creates a new DashboardV2alpha2RegexMapOptions object.
+func NewDashboardV2alpha2RegexMapOptions() *DashboardV2alpha2RegexMapOptions {
+ return &DashboardV2alpha2RegexMapOptions{
+ Result: *NewDashboardValueMappingResult(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardV2alpha2SpecialValueMapOptions struct {
+ // Special value to match against
+ Match DashboardSpecialValueMatch `json:"match"`
+ // Config to apply when the value matches the special value
+ Result DashboardValueMappingResult `json:"result"`
+}
+
+// NewDashboardV2alpha2SpecialValueMapOptions creates a new DashboardV2alpha2SpecialValueMapOptions object.
+func NewDashboardV2alpha2SpecialValueMapOptions() *DashboardV2alpha2SpecialValueMapOptions {
+ return &DashboardV2alpha2SpecialValueMapOptions{
+ Result: *NewDashboardValueMappingResult(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type DashboardRepeatOptionsDirection string
+
+const (
+ DashboardRepeatOptionsDirectionH DashboardRepeatOptionsDirection = "h"
+ DashboardRepeatOptionsDirectionV DashboardRepeatOptionsDirection = "v"
+)
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingGroupSpecVisibility string
+
+const (
+ DashboardConditionalRenderingGroupSpecVisibilityShow DashboardConditionalRenderingGroupSpecVisibility = "show"
+ DashboardConditionalRenderingGroupSpecVisibilityHide DashboardConditionalRenderingGroupSpecVisibility = "hide"
+)
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingGroupSpecCondition string
+
+const (
+ DashboardConditionalRenderingGroupSpecConditionAnd DashboardConditionalRenderingGroupSpecCondition = "and"
+ DashboardConditionalRenderingGroupSpecConditionOr DashboardConditionalRenderingGroupSpecCondition = "or"
+)
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingVariableSpecOperator string
+
+const (
+ DashboardConditionalRenderingVariableSpecOperatorEquals DashboardConditionalRenderingVariableSpecOperator = "equals"
+ DashboardConditionalRenderingVariableSpecOperatorNotEquals DashboardConditionalRenderingVariableSpecOperator = "notEquals"
+)
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutSpecColumnWidthMode string
+
+const (
+ DashboardAutoGridLayoutSpecColumnWidthModeNarrow DashboardAutoGridLayoutSpecColumnWidthMode = "narrow"
+ DashboardAutoGridLayoutSpecColumnWidthModeStandard DashboardAutoGridLayoutSpecColumnWidthMode = "standard"
+ DashboardAutoGridLayoutSpecColumnWidthModeWide DashboardAutoGridLayoutSpecColumnWidthMode = "wide"
+ DashboardAutoGridLayoutSpecColumnWidthModeCustom DashboardAutoGridLayoutSpecColumnWidthMode = "custom"
+)
+
+// +k8s:openapi-gen=true
+type DashboardAutoGridLayoutSpecRowHeightMode string
+
+const (
+ DashboardAutoGridLayoutSpecRowHeightModeShort DashboardAutoGridLayoutSpecRowHeightMode = "short"
+ DashboardAutoGridLayoutSpecRowHeightModeStandard DashboardAutoGridLayoutSpecRowHeightMode = "standard"
+ DashboardAutoGridLayoutSpecRowHeightModeTall DashboardAutoGridLayoutSpecRowHeightMode = "tall"
+ DashboardAutoGridLayoutSpecRowHeightModeCustom DashboardAutoGridLayoutSpecRowHeightMode = "custom"
+)
+
+// +k8s:openapi-gen=true
+type DashboardTimeSettingsSpecWeekStart string
+
+const (
+ DashboardTimeSettingsSpecWeekStartSaturday DashboardTimeSettingsSpecWeekStart = "saturday"
+ DashboardTimeSettingsSpecWeekStartMonday DashboardTimeSettingsSpecWeekStart = "monday"
+ DashboardTimeSettingsSpecWeekStartSunday DashboardTimeSettingsSpecWeekStart = "sunday"
+)
+
+// +k8s:openapi-gen=true
+type DashboardQueryVariableSpecStaticOptionsOrder string
+
+const (
+ DashboardQueryVariableSpecStaticOptionsOrderBefore DashboardQueryVariableSpecStaticOptionsOrder = "before"
+ DashboardQueryVariableSpecStaticOptionsOrderAfter DashboardQueryVariableSpecStaticOptionsOrder = "after"
+ DashboardQueryVariableSpecStaticOptionsOrderSorted DashboardQueryVariableSpecStaticOptionsOrder = "sorted"
+)
+
+// +k8s:openapi-gen=true
+type DashboardPanelKindOrLibraryPanelKind struct {
+ PanelKind *DashboardPanelKind `json:"PanelKind,omitempty"`
+ LibraryPanelKind *DashboardLibraryPanelKind `json:"LibraryPanelKind,omitempty"`
+}
+
+// NewDashboardPanelKindOrLibraryPanelKind creates a new DashboardPanelKindOrLibraryPanelKind object.
+func NewDashboardPanelKindOrLibraryPanelKind() *DashboardPanelKindOrLibraryPanelKind {
+ return &DashboardPanelKindOrLibraryPanelKind{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardPanelKindOrLibraryPanelKind` as JSON.
+func (resource DashboardPanelKindOrLibraryPanelKind) MarshalJSON() ([]byte, error) {
+ if resource.PanelKind != nil {
+ return json.Marshal(resource.PanelKind)
+ }
+ if resource.LibraryPanelKind != nil {
+ return json.Marshal(resource.LibraryPanelKind)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardPanelKindOrLibraryPanelKind` from JSON.
+func (resource *DashboardPanelKindOrLibraryPanelKind) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["kind"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "LibraryPanel":
+ var dashboardLibraryPanelKind DashboardLibraryPanelKind
+ if err := json.Unmarshal(raw, &dashboardLibraryPanelKind); err != nil {
+ return err
+ }
+
+ resource.LibraryPanelKind = &dashboardLibraryPanelKind
+ return nil
+ case "Panel":
+ var dashboardPanelKind DashboardPanelKind
+ if err := json.Unmarshal(raw, &dashboardPanelKind); err != nil {
+ return err
+ }
+
+ resource.PanelKind = &dashboardPanelKind
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap struct {
+ ValueMap *DashboardValueMap `json:"ValueMap,omitempty"`
+ RangeMap *DashboardRangeMap `json:"RangeMap,omitempty"`
+ RegexMap *DashboardRegexMap `json:"RegexMap,omitempty"`
+ SpecialValueMap *DashboardSpecialValueMap `json:"SpecialValueMap,omitempty"`
+}
+
+// NewDashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap creates a new DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap object.
+func NewDashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap() *DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap {
+ return &DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap` as JSON.
+func (resource DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap) MarshalJSON() ([]byte, error) {
+ if resource.ValueMap != nil {
+ return json.Marshal(resource.ValueMap)
+ }
+ if resource.RangeMap != nil {
+ return json.Marshal(resource.RangeMap)
+ }
+ if resource.RegexMap != nil {
+ return json.Marshal(resource.RegexMap)
+ }
+ if resource.SpecialValueMap != nil {
+ return json.Marshal(resource.SpecialValueMap)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap` from JSON.
+func (resource *DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["type"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "range":
+ var dashboardRangeMap DashboardRangeMap
+ if err := json.Unmarshal(raw, &dashboardRangeMap); err != nil {
+ return err
+ }
+
+ resource.RangeMap = &dashboardRangeMap
+ return nil
+ case "regex":
+ var dashboardRegexMap DashboardRegexMap
+ if err := json.Unmarshal(raw, &dashboardRegexMap); err != nil {
+ return err
+ }
+
+ resource.RegexMap = &dashboardRegexMap
+ return nil
+ case "special":
+ var dashboardSpecialValueMap DashboardSpecialValueMap
+ if err := json.Unmarshal(raw, &dashboardSpecialValueMap); err != nil {
+ return err
+ }
+
+ resource.SpecialValueMap = &dashboardSpecialValueMap
+ return nil
+ case "value":
+ var dashboardValueMap DashboardValueMap
+ if err := json.Unmarshal(raw, &dashboardValueMap); err != nil {
+ return err
+ }
+
+ resource.ValueMap = &dashboardValueMap
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind struct {
+ GridLayoutKind *DashboardGridLayoutKind `json:"GridLayoutKind,omitempty"`
+ AutoGridLayoutKind *DashboardAutoGridLayoutKind `json:"AutoGridLayoutKind,omitempty"`
+ TabsLayoutKind *DashboardTabsLayoutKind `json:"TabsLayoutKind,omitempty"`
+ RowsLayoutKind *DashboardRowsLayoutKind `json:"RowsLayoutKind,omitempty"`
+}
+
+// NewDashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind creates a new DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind object.
+func NewDashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind() *DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind {
+ return &DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind` as JSON.
+func (resource DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind) MarshalJSON() ([]byte, error) {
+ if resource.GridLayoutKind != nil {
+ return json.Marshal(resource.GridLayoutKind)
+ }
+ if resource.AutoGridLayoutKind != nil {
+ return json.Marshal(resource.AutoGridLayoutKind)
+ }
+ if resource.TabsLayoutKind != nil {
+ return json.Marshal(resource.TabsLayoutKind)
+ }
+ if resource.RowsLayoutKind != nil {
+ return json.Marshal(resource.RowsLayoutKind)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind` from JSON.
+func (resource *DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["kind"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "AutoGridLayout":
+ var dashboardAutoGridLayoutKind DashboardAutoGridLayoutKind
+ if err := json.Unmarshal(raw, &dashboardAutoGridLayoutKind); err != nil {
+ return err
+ }
+
+ resource.AutoGridLayoutKind = &dashboardAutoGridLayoutKind
+ return nil
+ case "GridLayout":
+ var dashboardGridLayoutKind DashboardGridLayoutKind
+ if err := json.Unmarshal(raw, &dashboardGridLayoutKind); err != nil {
+ return err
+ }
+
+ resource.GridLayoutKind = &dashboardGridLayoutKind
+ return nil
+ case "RowsLayout":
+ var dashboardRowsLayoutKind DashboardRowsLayoutKind
+ if err := json.Unmarshal(raw, &dashboardRowsLayoutKind); err != nil {
+ return err
+ }
+
+ resource.RowsLayoutKind = &dashboardRowsLayoutKind
+ return nil
+ case "TabsLayout":
+ var dashboardTabsLayoutKind DashboardTabsLayoutKind
+ if err := json.Unmarshal(raw, &dashboardTabsLayoutKind); err != nil {
+ return err
+ }
+
+ resource.TabsLayoutKind = &dashboardTabsLayoutKind
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind struct {
+ ConditionalRenderingVariableKind *DashboardConditionalRenderingVariableKind `json:"ConditionalRenderingVariableKind,omitempty"`
+ ConditionalRenderingDataKind *DashboardConditionalRenderingDataKind `json:"ConditionalRenderingDataKind,omitempty"`
+ ConditionalRenderingTimeRangeSizeKind *DashboardConditionalRenderingTimeRangeSizeKind `json:"ConditionalRenderingTimeRangeSizeKind,omitempty"`
+}
+
+// NewDashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind creates a new DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind object.
+func NewDashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind() *DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind {
+ return &DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind` as JSON.
+func (resource DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind) MarshalJSON() ([]byte, error) {
+ if resource.ConditionalRenderingVariableKind != nil {
+ return json.Marshal(resource.ConditionalRenderingVariableKind)
+ }
+ if resource.ConditionalRenderingDataKind != nil {
+ return json.Marshal(resource.ConditionalRenderingDataKind)
+ }
+ if resource.ConditionalRenderingTimeRangeSizeKind != nil {
+ return json.Marshal(resource.ConditionalRenderingTimeRangeSizeKind)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind` from JSON.
+func (resource *DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["kind"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "ConditionalRenderingData":
+ var dashboardConditionalRenderingDataKind DashboardConditionalRenderingDataKind
+ if err := json.Unmarshal(raw, &dashboardConditionalRenderingDataKind); err != nil {
+ return err
+ }
+
+ resource.ConditionalRenderingDataKind = &dashboardConditionalRenderingDataKind
+ return nil
+ case "ConditionalRenderingTimeRangeSize":
+ var dashboardConditionalRenderingTimeRangeSizeKind DashboardConditionalRenderingTimeRangeSizeKind
+ if err := json.Unmarshal(raw, &dashboardConditionalRenderingTimeRangeSizeKind); err != nil {
+ return err
+ }
+
+ resource.ConditionalRenderingTimeRangeSizeKind = &dashboardConditionalRenderingTimeRangeSizeKind
+ return nil
+ case "ConditionalRenderingVariable":
+ var dashboardConditionalRenderingVariableKind DashboardConditionalRenderingVariableKind
+ if err := json.Unmarshal(raw, &dashboardConditionalRenderingVariableKind); err != nil {
+ return err
+ }
+
+ resource.ConditionalRenderingVariableKind = &dashboardConditionalRenderingVariableKind
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind struct {
+ GridLayoutKind *DashboardGridLayoutKind `json:"GridLayoutKind,omitempty"`
+ RowsLayoutKind *DashboardRowsLayoutKind `json:"RowsLayoutKind,omitempty"`
+ AutoGridLayoutKind *DashboardAutoGridLayoutKind `json:"AutoGridLayoutKind,omitempty"`
+ TabsLayoutKind *DashboardTabsLayoutKind `json:"TabsLayoutKind,omitempty"`
+}
+
+// NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind creates a new DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind object.
+func NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind() *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind {
+ return &DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind` as JSON.
+func (resource DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind) MarshalJSON() ([]byte, error) {
+ if resource.GridLayoutKind != nil {
+ return json.Marshal(resource.GridLayoutKind)
+ }
+ if resource.RowsLayoutKind != nil {
+ return json.Marshal(resource.RowsLayoutKind)
+ }
+ if resource.AutoGridLayoutKind != nil {
+ return json.Marshal(resource.AutoGridLayoutKind)
+ }
+ if resource.TabsLayoutKind != nil {
+ return json.Marshal(resource.TabsLayoutKind)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind` from JSON.
+func (resource *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["kind"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "AutoGridLayout":
+ var dashboardAutoGridLayoutKind DashboardAutoGridLayoutKind
+ if err := json.Unmarshal(raw, &dashboardAutoGridLayoutKind); err != nil {
+ return err
+ }
+
+ resource.AutoGridLayoutKind = &dashboardAutoGridLayoutKind
+ return nil
+ case "GridLayout":
+ var dashboardGridLayoutKind DashboardGridLayoutKind
+ if err := json.Unmarshal(raw, &dashboardGridLayoutKind); err != nil {
+ return err
+ }
+
+ resource.GridLayoutKind = &dashboardGridLayoutKind
+ return nil
+ case "RowsLayout":
+ var dashboardRowsLayoutKind DashboardRowsLayoutKind
+ if err := json.Unmarshal(raw, &dashboardRowsLayoutKind); err != nil {
+ return err
+ }
+
+ resource.RowsLayoutKind = &dashboardRowsLayoutKind
+ return nil
+ case "TabsLayout":
+ var dashboardTabsLayoutKind DashboardTabsLayoutKind
+ if err := json.Unmarshal(raw, &dashboardTabsLayoutKind); err != nil {
+ return err
+ }
+
+ resource.TabsLayoutKind = &dashboardTabsLayoutKind
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind struct {
+ QueryVariableKind *DashboardQueryVariableKind `json:"QueryVariableKind,omitempty"`
+ TextVariableKind *DashboardTextVariableKind `json:"TextVariableKind,omitempty"`
+ ConstantVariableKind *DashboardConstantVariableKind `json:"ConstantVariableKind,omitempty"`
+ DatasourceVariableKind *DashboardDatasourceVariableKind `json:"DatasourceVariableKind,omitempty"`
+ IntervalVariableKind *DashboardIntervalVariableKind `json:"IntervalVariableKind,omitempty"`
+ CustomVariableKind *DashboardCustomVariableKind `json:"CustomVariableKind,omitempty"`
+ GroupByVariableKind *DashboardGroupByVariableKind `json:"GroupByVariableKind,omitempty"`
+ AdhocVariableKind *DashboardAdhocVariableKind `json:"AdhocVariableKind,omitempty"`
+}
+
+// NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind creates a new DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind object.
+func NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind() *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind {
+ return &DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` as JSON.
+func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) MarshalJSON() ([]byte, error) {
+ if resource.QueryVariableKind != nil {
+ return json.Marshal(resource.QueryVariableKind)
+ }
+ if resource.TextVariableKind != nil {
+ return json.Marshal(resource.TextVariableKind)
+ }
+ if resource.ConstantVariableKind != nil {
+ return json.Marshal(resource.ConstantVariableKind)
+ }
+ if resource.DatasourceVariableKind != nil {
+ return json.Marshal(resource.DatasourceVariableKind)
+ }
+ if resource.IntervalVariableKind != nil {
+ return json.Marshal(resource.IntervalVariableKind)
+ }
+ if resource.CustomVariableKind != nil {
+ return json.Marshal(resource.CustomVariableKind)
+ }
+ if resource.GroupByVariableKind != nil {
+ return json.Marshal(resource.GroupByVariableKind)
+ }
+ if resource.AdhocVariableKind != nil {
+ return json.Marshal(resource.AdhocVariableKind)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` from JSON.
+func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ // FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
+ parsedAsMap := make(map[string]interface{})
+ if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
+ return err
+ }
+
+ discriminator, found := parsedAsMap["kind"]
+ if !found {
+ return nil
+ }
+
+ switch discriminator {
+ case "AdhocVariable":
+ var dashboardAdhocVariableKind DashboardAdhocVariableKind
+ if err := json.Unmarshal(raw, &dashboardAdhocVariableKind); err != nil {
+ return err
+ }
+
+ resource.AdhocVariableKind = &dashboardAdhocVariableKind
+ return nil
+ case "ConstantVariable":
+ var dashboardConstantVariableKind DashboardConstantVariableKind
+ if err := json.Unmarshal(raw, &dashboardConstantVariableKind); err != nil {
+ return err
+ }
+
+ resource.ConstantVariableKind = &dashboardConstantVariableKind
+ return nil
+ case "CustomVariable":
+ var dashboardCustomVariableKind DashboardCustomVariableKind
+ if err := json.Unmarshal(raw, &dashboardCustomVariableKind); err != nil {
+ return err
+ }
+
+ resource.CustomVariableKind = &dashboardCustomVariableKind
+ return nil
+ case "DatasourceVariable":
+ var dashboardDatasourceVariableKind DashboardDatasourceVariableKind
+ if err := json.Unmarshal(raw, &dashboardDatasourceVariableKind); err != nil {
+ return err
+ }
+
+ resource.DatasourceVariableKind = &dashboardDatasourceVariableKind
+ return nil
+ case "GroupByVariable":
+ var dashboardGroupByVariableKind DashboardGroupByVariableKind
+ if err := json.Unmarshal(raw, &dashboardGroupByVariableKind); err != nil {
+ return err
+ }
+
+ resource.GroupByVariableKind = &dashboardGroupByVariableKind
+ return nil
+ case "IntervalVariable":
+ var dashboardIntervalVariableKind DashboardIntervalVariableKind
+ if err := json.Unmarshal(raw, &dashboardIntervalVariableKind); err != nil {
+ return err
+ }
+
+ resource.IntervalVariableKind = &dashboardIntervalVariableKind
+ return nil
+ case "QueryVariable":
+ var dashboardQueryVariableKind DashboardQueryVariableKind
+ if err := json.Unmarshal(raw, &dashboardQueryVariableKind); err != nil {
+ return err
+ }
+
+ resource.QueryVariableKind = &dashboardQueryVariableKind
+ return nil
+ case "TextVariable":
+ var dashboardTextVariableKind DashboardTextVariableKind
+ if err := json.Unmarshal(raw, &dashboardTextVariableKind); err != nil {
+ return err
+ }
+
+ resource.TextVariableKind = &dashboardTextVariableKind
+ return nil
+ }
+
+ return nil
+}
+
+// +k8s:openapi-gen=true
+type DashboardStringOrArrayOfString struct {
+ String *string `json:"String,omitempty"`
+ ArrayOfString []string `json:"ArrayOfString,omitempty"`
+}
+
+// NewDashboardStringOrArrayOfString creates a new DashboardStringOrArrayOfString object.
+func NewDashboardStringOrArrayOfString() *DashboardStringOrArrayOfString {
+ return &DashboardStringOrArrayOfString{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardStringOrArrayOfString` as JSON.
+func (resource DashboardStringOrArrayOfString) MarshalJSON() ([]byte, error) {
+ if resource.String != nil {
+ return json.Marshal(resource.String)
+ }
+
+ if resource.ArrayOfString != nil {
+ return json.Marshal(resource.ArrayOfString)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardStringOrArrayOfString` from JSON.
+func (resource *DashboardStringOrArrayOfString) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ var errList []error
+
+ // String
+ var String string
+ if err := json.Unmarshal(raw, &String); err != nil {
+ errList = append(errList, err)
+ resource.String = nil
+ } else {
+ resource.String = &String
+ return nil
+ }
+
+ // ArrayOfString
+ var ArrayOfString []string
+ if err := json.Unmarshal(raw, &ArrayOfString); err != nil {
+ errList = append(errList, err)
+ resource.ArrayOfString = nil
+ } else {
+ resource.ArrayOfString = ArrayOfString
+ return nil
+ }
+
+ return errors.Join(errList...)
+}
+
+// +k8s:openapi-gen=true
+type DashboardStringOrFloat64 struct {
+ String *string `json:"String,omitempty"`
+ Float64 *float64 `json:"Float64,omitempty"`
+}
+
+// NewDashboardStringOrFloat64 creates a new DashboardStringOrFloat64 object.
+func NewDashboardStringOrFloat64() *DashboardStringOrFloat64 {
+ return &DashboardStringOrFloat64{}
+}
+
+// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardStringOrFloat64` as JSON.
+func (resource DashboardStringOrFloat64) MarshalJSON() ([]byte, error) {
+ if resource.String != nil {
+ return json.Marshal(resource.String)
+ }
+
+ if resource.Float64 != nil {
+ return json.Marshal(resource.Float64)
+ }
+
+ return []byte("null"), nil
+}
+
+// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardStringOrFloat64` from JSON.
+func (resource *DashboardStringOrFloat64) UnmarshalJSON(raw []byte) error {
+ if raw == nil {
+ return nil
+ }
+
+ var errList []error
+
+ // String
+ var String string
+ if err := json.Unmarshal(raw, &String); err != nil {
+ errList = append(errList, err)
+ resource.String = nil
+ } else {
+ resource.String = &String
+ return nil
+ }
+
+ // Float64
+ var Float64 float64
+ if err := json.Unmarshal(raw, &Float64); err != nil {
+ errList = append(errList, err)
+ resource.Float64 = nil
+ } else {
+ resource.Float64 = &Float64
+ return nil
+ }
+
+ return errors.Join(errList...)
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_status_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_status_gen.go
new file mode 100644
index 00000000000..322f9f072ec
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/dashboard_status_gen.go
@@ -0,0 +1,34 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v2alpha2
+
+// ConversionStatus is the status of the conversion of the dashboard.
+// +k8s:openapi-gen=true
+type DashboardConversionStatus struct {
+ // Whether from another version has failed.
+ // If true, means that the dashboard is not valid,
+ // and the caller should instead fetch the stored version.
+ Failed bool `json:"failed"`
+ // The version which was stored when the dashboard was created / updated.
+ // Fetching this version should always succeed.
+ StoredVersion string `json:"storedVersion"`
+ // The error message from the conversion.
+ // Empty if the conversion has not failed.
+ Error string `json:"error"`
+}
+
+// NewDashboardConversionStatus creates a new DashboardConversionStatus object.
+func NewDashboardConversionStatus() *DashboardConversionStatus {
+ return &DashboardConversionStatus{}
+}
+
+// +k8s:openapi-gen=true
+type DashboardStatus struct {
+ // Optional conversion status.
+ Conversion *DashboardConversionStatus `json:"conversion,omitempty"`
+}
+
+// NewDashboardStatus creates a new DashboardStatus object.
+func NewDashboardStatus() *DashboardStatus {
+ return &DashboardStatus{}
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/doc.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/doc.go
new file mode 100644
index 00000000000..95dba55d4cd
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/doc.go
@@ -0,0 +1,10 @@
+// +k8s:openapi-gen=true
+// +k8s:defaulter-gen=TypeMeta
+// +k8s:conversion-gen=github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard
+// +groupName=dashboard.grafana.app
+
+// NOTE (@radiohead): we do not use package-wide deepcopy generation
+// because grafana-app-sdk already provides deepcopy functions.
+// Kinds which are not generated by the SDK are explicitly opted in to deepcopy generation.
+
+package v2alpha2 // import "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/register.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/register.go
new file mode 100644
index 00000000000..0a68d910fb1
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/register.go
@@ -0,0 +1,103 @@
+package v2alpha2
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/grafana/grafana/pkg/apimachinery/utils"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+const (
+ GROUP = "dashboard.grafana.app"
+ VERSION = "v2alpha2"
+ APIVERSION = GROUP + "/" + VERSION
+)
+
+var DashboardResourceInfo = utils.NewResourceInfo(GROUP, VERSION,
+ "dashboards", "dashboard", "Dashboard",
+ func() runtime.Object { return &Dashboard{} },
+ func() runtime.Object { return &DashboardList{} },
+ utils.TableColumns{
+ Definition: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string", Format: "name"},
+ {Name: "Title", Type: "string", Format: "string", Description: "The dashboard name"},
+ {Name: "Created At", Type: "date"},
+ },
+ Reader: func(obj any) ([]interface{}, error) {
+ dash, ok := obj.(*Dashboard)
+ if ok {
+ if dash != nil {
+ return []interface{}{
+ dash.Name,
+ dash.Spec.Title,
+ dash.CreationTimestamp.UTC().Format(time.RFC3339),
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("expected dashboard")
+ },
+ },
+)
+
+var LibraryPanelResourceInfo = utils.NewResourceInfo(GROUP, VERSION,
+ "librarypanels", "librarypanel", "LibraryPanel",
+ func() runtime.Object { return &LibraryPanel{} },
+ func() runtime.Object { return &LibraryPanelList{} },
+ utils.TableColumns{
+ Definition: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string", Format: "name"},
+ {Name: "Title", Type: "string", Description: "The dashboard name"},
+ {Name: "Type", Type: "string", Description: "the panel type"},
+ {Name: "Created At", Type: "date"},
+ },
+ Reader: func(obj any) ([]interface{}, error) {
+ panel, ok := obj.(*LibraryPanel)
+ if ok {
+ if panel != nil {
+ return []interface{}{
+ panel.Name,
+ panel.Spec.Title,
+ panel.Spec.Type,
+ panel.CreationTimestamp.UTC().Format(time.RFC3339),
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("expected library panel")
+ },
+ },
+)
+
+var (
+ SchemeBuilder runtime.SchemeBuilder
+ localSchemeBuilder = &SchemeBuilder
+ AddToScheme = localSchemeBuilder.AddToScheme
+ schemeGroupVersion = schema.GroupVersion{Group: GROUP, Version: VERSION}
+)
+
+func init() {
+ localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
+}
+
+// Adds the list of known types to the given scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+ scheme.AddKnownTypes(schemeGroupVersion,
+ &Dashboard{},
+ &DashboardList{},
+ &DashboardWithAccessInfo{},
+ &DashboardVersionList{},
+ &VersionsQueryOptions{},
+ &LibraryPanel{},
+ &LibraryPanelList{},
+ &metav1.PartialObjectMetadata{},
+ &metav1.PartialObjectMetadataList{},
+ )
+ metav1.AddToGroupVersion(scheme, schemeGroupVersion)
+ return nil
+}
+
+func addDefaultingFuncs(scheme *runtime.Scheme) error {
+ return RegisterDefaults(scheme)
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/types.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/types.go
new file mode 100644
index 00000000000..b40a86fe94e
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/types.go
@@ -0,0 +1,149 @@
+package v2alpha2
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
+ common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
+)
+
+// +k8s:deepcopy-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type DashboardVersionList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ Items []DashboardVersionInfo `json:"items"`
+}
+
+// +k8s:deepcopy-gen=true
+type DashboardVersionInfo struct {
+ // The internal ID for this version (will be replaced with resourceVersion)
+ Version int `json:"version"`
+
+ // If the dashboard came from a previous version, it is set here
+ ParentVersion int `json:"parentVersion,omitempty"`
+
+ // The creation timestamp for this version
+ Created int64 `json:"created"`
+
+ // The user who created this version
+ CreatedBy string `json:"createdBy,omitempty"`
+
+ // Message passed while saving the version
+ Message string `json:"message,omitempty"`
+}
+
+// +k8s:deepcopy-gen=true
+// +k8s:conversion-gen:explicit-from=net/url.Values
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type VersionsQueryOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // Path is the URL path
+ // +optional
+ Path string `json:"path,omitempty"`
+
+ // +optional
+ Version int64 `json:"version,omitempty"`
+}
+
+// +k8s:deepcopy-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type LibraryPanel struct {
+ metav1.TypeMeta `json:",inline"`
+ // Standard object's metadata
+ // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Panel properties
+ Spec LibraryPanelSpec `json:"spec"`
+
+ // Status will show errors
+ Status *LibraryPanelStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type LibraryPanelList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+
+ Items []LibraryPanel `json:"items"`
+}
+
+// +k8s:deepcopy-gen=true
+type LibraryPanelSpec struct {
+ // The panel type
+ Type string `json:"type"`
+
+ // The panel type
+ PluginVersion string `json:"pluginVersion,omitempty"`
+
+ // The panel title
+ Title string `json:"title,omitempty"`
+
+ // Library panel description
+ Description string `json:"description,omitempty"`
+
+ // The options schema depends on the panel type
+ Options common.Unstructured `json:"options"`
+
+ // The fieldConfig schema depends on the panel type
+ FieldConfig common.Unstructured `json:"fieldConfig"`
+
+ // The default datasource type
+ Datasource *data.DataSourceRef `json:"datasource,omitempty"`
+
+ // The datasource queries
+ // +listType=set
+ Targets []data.DataQuery `json:"targets,omitempty"`
+}
+
+// +k8s:deepcopy-gen=true
+type LibraryPanelStatus struct {
+ // Translation warnings (mostly things that were in SQL columns but not found in the saved body)
+ Warnings []string `json:"warnings,omitempty"`
+
+ // The properties previously stored in SQL that are not included in this model
+ Missing common.Unstructured `json:"missing,omitempty"`
+}
+
+// This is like the legacy DTO where access and metadata are all returned in a single call
+// +k8s:deepcopy-gen=true
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type DashboardWithAccessInfo struct {
+ Dashboard `json:",inline"`
+
+ Access DashboardAccess `json:"access"`
+}
+
+// Information about how the requesting user can use a given dashboard
+// +k8s:deepcopy-gen=true
+type DashboardAccess struct {
+ // Metadata fields
+ Slug string `json:"slug,omitempty"`
+ Url string `json:"url,omitempty"`
+
+ // The permissions part
+ CanSave bool `json:"canSave"`
+ CanEdit bool `json:"canEdit"`
+ CanAdmin bool `json:"canAdmin"`
+ CanStar bool `json:"canStar"`
+ CanDelete bool `json:"canDelete"`
+ AnnotationsPermissions *AnnotationPermission `json:"annotationsPermissions"`
+}
+
+// +k8s:deepcopy-gen=true
+type AnnotationPermission struct {
+ Dashboard AnnotationActions `json:"dashboard"`
+ Organization AnnotationActions `json:"organization"`
+}
+
+// +k8s:deepcopy-gen=true
+type AnnotationActions struct {
+ CanAdd bool `json:"canAdd"`
+ CanEdit bool `json:"canEdit"`
+ CanDelete bool `json:"canDelete"`
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/validation.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/validation.go
new file mode 100644
index 00000000000..9b01c53a3e1
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/validation.go
@@ -0,0 +1,84 @@
+package v2alpha2
+
+import (
+ _ "embed"
+ json "encoding/json"
+ fmt "fmt"
+ "strings"
+ "sync"
+
+ "k8s.io/apimachinery/pkg/util/validation/field"
+
+ "cuelang.org/go/cue"
+ "cuelang.org/go/cue/cuecontext"
+ "cuelang.org/go/cue/errors"
+ cuejson "cuelang.org/go/encoding/json"
+)
+
+func ValidateDashboardSpec(obj *Dashboard) field.ErrorList {
+ data, err := json.Marshal(obj.Spec)
+ if err != nil {
+ return field.ErrorList{
+ field.Invalid(field.NewPath("spec"), field.OmitValueType{}, err.Error()),
+ }
+ }
+
+ if err := cuejson.Validate(data, getCueSchema()); err != nil {
+ errs := field.ErrorList{}
+
+ for _, e := range errors.Errors(err) {
+ if
+ // We don't want to return confusing "empty disjunction" errors,
+ // because the users don't necessarily understand what to do with them.
+ // For empty disjunctions, CUE will also return more specific errors,
+ // so we can safely ignore the generic ones.
+ strings.Contains(e.Error(), "disjunction") ||
+ // We don't want to return errors about unknown fields either.
+ strings.Contains(e.Error(), "field not allowed") {
+ continue
+ }
+
+ if strings.Contains(e.Error(), "mismatched types null and list") {
+ // Go populates empty slices as nil, which the cue validator does not like
+ continue
+ }
+
+ // We want to manually format the error message,
+ // because e.Error() contains the full CUE path.
+ format, args := e.Msg()
+
+ errs = append(errs, field.Invalid(
+ field.NewPath(formatErrorPath(e.Path())),
+ field.OmitValueType{},
+ fmt.Sprintf(format, args...),
+ ))
+ }
+
+ return errs
+ }
+
+ return nil
+}
+
+func formatErrorPath(path []string) string {
+ return strings.Join(path, ".")
+}
+
+var (
+ compiledSchema cue.Value
+ getSchemaOnce sync.Once
+)
+
+//go:embed dashboard_spec.cue
+var schemaSource string
+
+func getCueSchema() cue.Value {
+ getSchemaOnce.Do(func() {
+ cueCtx := cuecontext.New()
+ compiledSchema = cueCtx.CompileString(schemaSource).LookupPath(
+ cue.ParsePath("DashboardSpec"),
+ )
+ })
+
+ return compiledSchema
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.conversion.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.conversion.go
new file mode 100644
index 00000000000..3159ff2e0f7
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.conversion.go
@@ -0,0 +1,175 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+// SPDX-License-Identifier: AGPL-3.0-only
+
+// Code generated by conversion-gen. DO NOT EDIT.
+
+package v2alpha2
+
+import (
+ url "net/url"
+ unsafe "unsafe"
+
+ dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard"
+ conversion "k8s.io/apimachinery/pkg/conversion"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+func init() {
+ localSchemeBuilder.Register(RegisterConversions)
+}
+
+// RegisterConversions adds conversion functions to the given scheme.
+// Public to allow building arbitrary schemes.
+func RegisterConversions(s *runtime.Scheme) error {
+ if err := s.AddGeneratedConversionFunc((*AnnotationActions)(nil), (*dashboard.AnnotationActions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(a.(*AnnotationActions), b.(*dashboard.AnnotationActions), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*dashboard.AnnotationActions)(nil), (*AnnotationActions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(a.(*dashboard.AnnotationActions), b.(*AnnotationActions), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*AnnotationPermission)(nil), (*dashboard.AnnotationPermission)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v2alpha2_AnnotationPermission_To_dashboard_AnnotationPermission(a.(*AnnotationPermission), b.(*dashboard.AnnotationPermission), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*dashboard.AnnotationPermission)(nil), (*AnnotationPermission)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_dashboard_AnnotationPermission_To_v2alpha2_AnnotationPermission(a.(*dashboard.AnnotationPermission), b.(*AnnotationPermission), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*DashboardAccess)(nil), (*dashboard.DashboardAccess)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v2alpha2_DashboardAccess_To_dashboard_DashboardAccess(a.(*DashboardAccess), b.(*dashboard.DashboardAccess), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*dashboard.DashboardAccess)(nil), (*DashboardAccess)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_dashboard_DashboardAccess_To_v2alpha2_DashboardAccess(a.(*dashboard.DashboardAccess), b.(*DashboardAccess), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*url.Values)(nil), (*VersionsQueryOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_url_Values_To_v2alpha2_VersionsQueryOptions(a.(*url.Values), b.(*VersionsQueryOptions), scope)
+ }); err != nil {
+ return err
+ }
+ return nil
+}
+
+func autoConvert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(in *AnnotationActions, out *dashboard.AnnotationActions, s conversion.Scope) error {
+ out.CanAdd = in.CanAdd
+ out.CanEdit = in.CanEdit
+ out.CanDelete = in.CanDelete
+ return nil
+}
+
+// Convert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions is an autogenerated conversion function.
+func Convert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(in *AnnotationActions, out *dashboard.AnnotationActions, s conversion.Scope) error {
+ return autoConvert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(in, out, s)
+}
+
+func autoConvert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(in *dashboard.AnnotationActions, out *AnnotationActions, s conversion.Scope) error {
+ out.CanAdd = in.CanAdd
+ out.CanEdit = in.CanEdit
+ out.CanDelete = in.CanDelete
+ return nil
+}
+
+// Convert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions is an autogenerated conversion function.
+func Convert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(in *dashboard.AnnotationActions, out *AnnotationActions, s conversion.Scope) error {
+ return autoConvert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(in, out, s)
+}
+
+func autoConvert_v2alpha2_AnnotationPermission_To_dashboard_AnnotationPermission(in *AnnotationPermission, out *dashboard.AnnotationPermission, s conversion.Scope) error {
+ if err := Convert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(&in.Dashboard, &out.Dashboard, s); err != nil {
+ return err
+ }
+ if err := Convert_v2alpha2_AnnotationActions_To_dashboard_AnnotationActions(&in.Organization, &out.Organization, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_v2alpha2_AnnotationPermission_To_dashboard_AnnotationPermission is an autogenerated conversion function.
+func Convert_v2alpha2_AnnotationPermission_To_dashboard_AnnotationPermission(in *AnnotationPermission, out *dashboard.AnnotationPermission, s conversion.Scope) error {
+ return autoConvert_v2alpha2_AnnotationPermission_To_dashboard_AnnotationPermission(in, out, s)
+}
+
+func autoConvert_dashboard_AnnotationPermission_To_v2alpha2_AnnotationPermission(in *dashboard.AnnotationPermission, out *AnnotationPermission, s conversion.Scope) error {
+ if err := Convert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(&in.Dashboard, &out.Dashboard, s); err != nil {
+ return err
+ }
+ if err := Convert_dashboard_AnnotationActions_To_v2alpha2_AnnotationActions(&in.Organization, &out.Organization, s); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Convert_dashboard_AnnotationPermission_To_v2alpha2_AnnotationPermission is an autogenerated conversion function.
+func Convert_dashboard_AnnotationPermission_To_v2alpha2_AnnotationPermission(in *dashboard.AnnotationPermission, out *AnnotationPermission, s conversion.Scope) error {
+ return autoConvert_dashboard_AnnotationPermission_To_v2alpha2_AnnotationPermission(in, out, s)
+}
+
+func autoConvert_v2alpha2_DashboardAccess_To_dashboard_DashboardAccess(in *DashboardAccess, out *dashboard.DashboardAccess, s conversion.Scope) error {
+ out.Slug = in.Slug
+ out.Url = in.Url
+ out.CanSave = in.CanSave
+ out.CanEdit = in.CanEdit
+ out.CanAdmin = in.CanAdmin
+ out.CanStar = in.CanStar
+ out.CanDelete = in.CanDelete
+ out.AnnotationsPermissions = (*dashboard.AnnotationPermission)(unsafe.Pointer(in.AnnotationsPermissions))
+ return nil
+}
+
+// Convert_v2alpha2_DashboardAccess_To_dashboard_DashboardAccess is an autogenerated conversion function.
+func Convert_v2alpha2_DashboardAccess_To_dashboard_DashboardAccess(in *DashboardAccess, out *dashboard.DashboardAccess, s conversion.Scope) error {
+ return autoConvert_v2alpha2_DashboardAccess_To_dashboard_DashboardAccess(in, out, s)
+}
+
+func autoConvert_dashboard_DashboardAccess_To_v2alpha2_DashboardAccess(in *dashboard.DashboardAccess, out *DashboardAccess, s conversion.Scope) error {
+ out.Slug = in.Slug
+ out.Url = in.Url
+ out.CanSave = in.CanSave
+ out.CanEdit = in.CanEdit
+ out.CanAdmin = in.CanAdmin
+ out.CanStar = in.CanStar
+ out.CanDelete = in.CanDelete
+ out.AnnotationsPermissions = (*AnnotationPermission)(unsafe.Pointer(in.AnnotationsPermissions))
+ return nil
+}
+
+// Convert_dashboard_DashboardAccess_To_v2alpha2_DashboardAccess is an autogenerated conversion function.
+func Convert_dashboard_DashboardAccess_To_v2alpha2_DashboardAccess(in *dashboard.DashboardAccess, out *DashboardAccess, s conversion.Scope) error {
+ return autoConvert_dashboard_DashboardAccess_To_v2alpha2_DashboardAccess(in, out, s)
+}
+
+func autoConvert_url_Values_To_v2alpha2_VersionsQueryOptions(in *url.Values, out *VersionsQueryOptions, s conversion.Scope) error {
+ // WARNING: Field TypeMeta does not have json tag, skipping.
+
+ if values, ok := map[string][]string(*in)["path"]; ok && len(values) > 0 {
+ if err := runtime.Convert_Slice_string_To_string(&values, &out.Path, s); err != nil {
+ return err
+ }
+ } else {
+ out.Path = ""
+ }
+ if values, ok := map[string][]string(*in)["version"]; ok && len(values) > 0 {
+ if err := runtime.Convert_Slice_string_To_int64(&values, &out.Version, s); err != nil {
+ return err
+ }
+ } else {
+ out.Version = 0
+ }
+ return nil
+}
+
+// Convert_url_Values_To_v2alpha2_VersionsQueryOptions is an autogenerated conversion function.
+func Convert_url_Values_To_v2alpha2_VersionsQueryOptions(in *url.Values, out *VersionsQueryOptions, s conversion.Scope) error {
+ return autoConvert_url_Values_To_v2alpha2_VersionsQueryOptions(in, out, s)
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.deepcopy.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.deepcopy.go
new file mode 100644
index 00000000000..9a8a05f7f22
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.deepcopy.go
@@ -0,0 +1,283 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+// SPDX-License-Identifier: AGPL-3.0-only
+
+// Code generated by deepcopy-gen. DO NOT EDIT.
+
+package v2alpha2
+
+import (
+ v0alpha1 "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AnnotationActions) DeepCopyInto(out *AnnotationActions) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnnotationActions.
+func (in *AnnotationActions) DeepCopy() *AnnotationActions {
+ if in == nil {
+ return nil
+ }
+ out := new(AnnotationActions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AnnotationPermission) DeepCopyInto(out *AnnotationPermission) {
+ *out = *in
+ out.Dashboard = in.Dashboard
+ out.Organization = in.Organization
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnnotationPermission.
+func (in *AnnotationPermission) DeepCopy() *AnnotationPermission {
+ if in == nil {
+ return nil
+ }
+ out := new(AnnotationPermission)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DashboardAccess) DeepCopyInto(out *DashboardAccess) {
+ *out = *in
+ if in.AnnotationsPermissions != nil {
+ in, out := &in.AnnotationsPermissions, &out.AnnotationsPermissions
+ *out = new(AnnotationPermission)
+ **out = **in
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DashboardAccess.
+func (in *DashboardAccess) DeepCopy() *DashboardAccess {
+ if in == nil {
+ return nil
+ }
+ out := new(DashboardAccess)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DashboardVersionInfo) DeepCopyInto(out *DashboardVersionInfo) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DashboardVersionInfo.
+func (in *DashboardVersionInfo) DeepCopy() *DashboardVersionInfo {
+ if in == nil {
+ return nil
+ }
+ out := new(DashboardVersionInfo)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DashboardVersionList) DeepCopyInto(out *DashboardVersionList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]DashboardVersionInfo, len(*in))
+ copy(*out, *in)
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DashboardVersionList.
+func (in *DashboardVersionList) DeepCopy() *DashboardVersionList {
+ if in == nil {
+ return nil
+ }
+ out := new(DashboardVersionList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *DashboardVersionList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DashboardWithAccessInfo) DeepCopyInto(out *DashboardWithAccessInfo) {
+ *out = *in
+ in.Dashboard.DeepCopyInto(&out.Dashboard)
+ in.Access.DeepCopyInto(&out.Access)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DashboardWithAccessInfo.
+func (in *DashboardWithAccessInfo) DeepCopy() *DashboardWithAccessInfo {
+ if in == nil {
+ return nil
+ }
+ out := new(DashboardWithAccessInfo)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *DashboardWithAccessInfo) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LibraryPanel) DeepCopyInto(out *LibraryPanel) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ if in.Status != nil {
+ in, out := &in.Status, &out.Status
+ *out = new(LibraryPanelStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibraryPanel.
+func (in *LibraryPanel) DeepCopy() *LibraryPanel {
+ if in == nil {
+ return nil
+ }
+ out := new(LibraryPanel)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *LibraryPanel) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LibraryPanelList) DeepCopyInto(out *LibraryPanelList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]LibraryPanel, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibraryPanelList.
+func (in *LibraryPanelList) DeepCopy() *LibraryPanelList {
+ if in == nil {
+ return nil
+ }
+ out := new(LibraryPanelList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *LibraryPanelList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LibraryPanelSpec) DeepCopyInto(out *LibraryPanelSpec) {
+ *out = *in
+ in.Options.DeepCopyInto(&out.Options)
+ in.FieldConfig.DeepCopyInto(&out.FieldConfig)
+ if in.Datasource != nil {
+ in, out := &in.Datasource, &out.Datasource
+ *out = new(v0alpha1.DataSourceRef)
+ **out = **in
+ }
+ if in.Targets != nil {
+ in, out := &in.Targets, &out.Targets
+ *out = make([]v0alpha1.DataQuery, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibraryPanelSpec.
+func (in *LibraryPanelSpec) DeepCopy() *LibraryPanelSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(LibraryPanelSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LibraryPanelStatus) DeepCopyInto(out *LibraryPanelStatus) {
+ *out = *in
+ if in.Warnings != nil {
+ in, out := &in.Warnings, &out.Warnings
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+ in.Missing.DeepCopyInto(&out.Missing)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibraryPanelStatus.
+func (in *LibraryPanelStatus) DeepCopy() *LibraryPanelStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(LibraryPanelStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VersionsQueryOptions) DeepCopyInto(out *VersionsQueryOptions) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VersionsQueryOptions.
+func (in *VersionsQueryOptions) DeepCopy() *VersionsQueryOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(VersionsQueryOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *VersionsQueryOptions) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
diff --git a/pkg/apis/secret/v0alpha1/zz_generated.defaults.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.defaults.go
similarity index 96%
rename from pkg/apis/secret/v0alpha1/zz_generated.defaults.go
rename to apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.defaults.go
index 238fc2f4edc..efead5bdea7 100644
--- a/pkg/apis/secret/v0alpha1/zz_generated.defaults.go
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.defaults.go
@@ -5,7 +5,7 @@
// Code generated by defaulter-gen. DO NOT EDIT.
-package v0alpha1
+package v2alpha2
import (
runtime "k8s.io/apimachinery/pkg/runtime"
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi.go
new file mode 100644
index 00000000000..7ed5e3983d4
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi.go
@@ -0,0 +1,5094 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+// SPDX-License-Identifier: AGPL-3.0-only
+
+// Code generated by openapi-gen. DO NOT EDIT.
+
+package v2alpha2
+
+import (
+ common "k8s.io/kube-openapi/pkg/common"
+ spec "k8s.io/kube-openapi/pkg/validation/spec"
+)
+
+func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
+ return map[string]common.OpenAPIDefinition{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationActions": schema_pkg_apis_dashboard_v2alpha2_AnnotationActions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationPermission": schema_pkg_apis_dashboard_v2alpha2_AnnotationPermission(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.Dashboard": schema_pkg_apis_dashboard_v2alpha2_Dashboard(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAccess": schema_pkg_apis_dashboard_v2alpha2_DashboardAccess(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdHocFilterWithLabels": schema_pkg_apis_dashboard_v2alpha2_DashboardAdHocFilterWithLabels(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardAdhocVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardAdhocVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationPanelFilter": schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationPanelFilter(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQueryKind": schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationQueryKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQuerySpec": schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationQuerySpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemKind": schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutItemKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutItemSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridRepeatOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridRepeatOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingDataKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingDataSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingGroupKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingGroupSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingTimeRangeSizeKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingTimeRangeSizeSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardConstantVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardConstantVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConversionStatus": schema_pkg_apis_dashboard_v2alpha2_DashboardConversionStatus(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardCustomVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardCustomVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDashboardLink": schema_pkg_apis_dashboard_v2alpha2_DashboardDashboardLink(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataLink": schema_pkg_apis_dashboard_v2alpha2_DashboardDataLink(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind": schema_pkg_apis_dashboard_v2alpha2_DashboardDataQueryKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef": schema_pkg_apis_dashboard_v2alpha2_DashboardDataSourceRef(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataTransformerConfig": schema_pkg_apis_dashboard_v2alpha2_DashboardDataTransformerConfig(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardDatasourceVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardDatasourceVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDynamicConfigValue": schema_pkg_apis_dashboard_v2alpha2_DashboardDynamicConfigValue(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardElementReference": schema_pkg_apis_dashboard_v2alpha2_DashboardElementReference(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldColor": schema_pkg_apis_dashboard_v2alpha2_DashboardFieldColor(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfig": schema_pkg_apis_dashboard_v2alpha2_DashboardFieldConfig(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2alpha2_DashboardFieldConfigSource(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutItemKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutItemSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardGroupByVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardGroupByVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardIntervalVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardIntervalVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardJSONCodec": schema_pkg_apis_dashboard_v2alpha2_DashboardJSONCodec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKind": schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKindSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelKindSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelRef": schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelRef(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardList": schema_pkg_apis_dashboard_v2alpha2_DashboardList(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMatcherConfig": schema_pkg_apis_dashboard_v2alpha2_DashboardMatcherConfig(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMetadata": schema_pkg_apis_dashboard_v2alpha2_DashboardMetadata(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMetricFindValue": schema_pkg_apis_dashboard_v2alpha2_DashboardMetricFindValue(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKind": schema_pkg_apis_dashboard_v2alpha2_DashboardPanelKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKindOrLibraryPanelKind": schema_pkg_apis_dashboard_v2alpha2_DashboardPanelKindOrLibraryPanelKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQueryKind": schema_pkg_apis_dashboard_v2alpha2_DashboardPanelQueryKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQuerySpec": schema_pkg_apis_dashboard_v2alpha2_DashboardPanelQuerySpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardPanelSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupKind": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryGroupKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryGroupSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryOptionsSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryOptionsSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRangeMap": schema_pkg_apis_dashboard_v2alpha2_DashboardRangeMap(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRegexMap": schema_pkg_apis_dashboard_v2alpha2_DashboardRegexMap(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRepeatOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardRepeatOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowRepeatOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardRowRepeatOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowKind": schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutRowKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutRowSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpecialValueMap": schema_pkg_apis_dashboard_v2alpha2_DashboardSpecialValueMap(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStatus": schema_pkg_apis_dashboard_v2alpha2_DashboardStatus(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrArrayOfString": schema_pkg_apis_dashboard_v2alpha2_DashboardStringOrArrayOfString(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrFloat64": schema_pkg_apis_dashboard_v2alpha2_DashboardStringOrFloat64(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabRepeatOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardTabRepeatOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutKind": schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabKind": schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutTabKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutTabSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableKind": schema_pkg_apis_dashboard_v2alpha2_DashboardTextVariableKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardTextVariableSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThreshold": schema_pkg_apis_dashboard_v2alpha2_DashboardThreshold(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThresholdsConfig": schema_pkg_apis_dashboard_v2alpha2_DashboardThresholdsConfig(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2alpha2_DashboardTimeRangeOption(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardTimeSettingsSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTransformationKind": schema_pkg_apis_dashboard_v2alpha2_DashboardTransformationKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2FieldConfigSourceOverrides(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RangeMapOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2RangeMapOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RegexMapOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2RegexMapOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2SpecialValueMapOptions": schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2SpecialValueMapOptions(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMap": schema_pkg_apis_dashboard_v2alpha2_DashboardValueMap(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap": schema_pkg_apis_dashboard_v2alpha2_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult": schema_pkg_apis_dashboard_v2alpha2_DashboardValueMappingResult(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption": schema_pkg_apis_dashboard_v2alpha2_DashboardVariableOption(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVersionInfo": schema_pkg_apis_dashboard_v2alpha2_DashboardVersionInfo(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVersionList": schema_pkg_apis_dashboard_v2alpha2_DashboardVersionList(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigKind": schema_pkg_apis_dashboard_v2alpha2_DashboardVizConfigKind(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigSpec": schema_pkg_apis_dashboard_v2alpha2_DashboardVizConfigSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardWithAccessInfo": schema_pkg_apis_dashboard_v2alpha2_DashboardWithAccessInfo(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanel": schema_pkg_apis_dashboard_v2alpha2_LibraryPanel(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelList": schema_pkg_apis_dashboard_v2alpha2_LibraryPanelList(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelSpec": schema_pkg_apis_dashboard_v2alpha2_LibraryPanelSpec(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelStatus": schema_pkg_apis_dashboard_v2alpha2_LibraryPanelStatus(ref),
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.VersionsQueryOptions": schema_pkg_apis_dashboard_v2alpha2_VersionsQueryOptions(ref),
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_AnnotationActions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "canAdd": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canEdit": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canDelete": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"canAdd", "canEdit", "canDelete"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_AnnotationPermission(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "dashboard": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationActions"),
+ },
+ },
+ "organization": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationActions"),
+ },
+ },
+ },
+ Required: []string{"dashboard", "organization"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationActions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_Dashboard(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the Dashboard",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpec", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAccess(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Information about how the requesting user can use a given dashboard",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "slug": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Metadata fields",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "url": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "canSave": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The permissions part",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canEdit": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canAdmin": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canStar": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "canDelete": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "annotationsPermissions": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationPermission"),
+ },
+ },
+ },
+ Required: []string{"canSave", "canEdit", "canAdmin", "canStar", "canDelete", "annotationsPermissions"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.AnnotationPermission"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAdHocFilterWithLabels(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Define the AdHocFilterWithLabels type",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "key": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "operator": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "values": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "keyLabel": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "valueLabels": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "forceEdit": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "origin": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "condition": {
+ SchemaProps: spec.SchemaProps{
+ Description: "@deprecated",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"key", "operator", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAdhocVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Adhoc variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAdhocVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Adhoc variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"),
+ },
+ },
+ "baseFilters": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdHocFilterWithLabels"),
+ },
+ },
+ },
+ },
+ },
+ "filters": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdHocFilterWithLabels"),
+ },
+ },
+ },
+ },
+ },
+ "defaultKeys": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMetricFindValue"),
+ },
+ },
+ },
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "allowCustomValue": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "baseFilters", "filters", "defaultKeys", "hide", "skipUrlSync", "allowCustomValue"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdHocFilterWithLabels", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMetricFindValue"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationPanelFilter(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "exclude": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Should the specified panels be included or excluded",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "ids": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Panel IDs that should be included or excluded",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"ids"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationQueryKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQuerySpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQuerySpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAnnotationQuerySpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"),
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind"),
+ },
+ },
+ "enable": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "iconColor": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "builtIn": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "filter": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationPanelFilter"),
+ },
+ },
+ "legacyOptions": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Catch-all field for datasource-specific properties",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"enable", "hide", "iconColor", "name"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutItemKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutItemSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "element": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardElementReference"),
+ },
+ },
+ "repeat": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridRepeatOptions"),
+ },
+ },
+ "conditionalRendering": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind"),
+ },
+ },
+ },
+ Required: []string{"element"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridRepeatOptions", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardElementReference"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "maxColumnCount": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "columnWidthMode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "columnWidth": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "rowHeightMode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "rowHeight": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "fillScreen": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"columnWidthMode", "rowHeightMode", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutItemKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardAutoGridRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingDataKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingDataSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingGroupKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingGroupSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "visibility": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "condition": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"visibility", "condition", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingTimeRangeSizeKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingTimeRangeSizeSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "ConditionalRenderingVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKind"),
+ },
+ },
+ "ConditionalRenderingDataKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataKind"),
+ },
+ },
+ "ConditionalRenderingTimeRangeSizeKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeKind"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingDataKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingTimeRangeSizeKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingVariableKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConditionalRenderingVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "variable": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "operator": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"variable", "operator", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConstantVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Constant variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConstantVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Constant variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "query", "current", "hide", "skipUrlSync"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardConversionStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "ConversionStatus is the status of the conversion of the dashboard.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "failed": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Whether from another version has failed. If true, means that the dashboard is not valid, and the caller should instead fetch the stored version.",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "storedVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The version which was stored when the dashboard was created / updated. Fetching this version should always succeed.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "error": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The error message from the conversion. Empty if the conversion has not failed.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"failed", "storedVersion", "error"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardCustomVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Custom variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardCustomVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Custom variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "multi": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "includeAll": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "allValue": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "allowCustomValue": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "query", "current", "options", "multi", "includeAll", "hide", "skipUrlSync", "allowCustomValue"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDashboardLink(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Links with references to other dashboards or external resources",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Title to display with the link",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) FIXME: The type is generated as `type: DashboardLinkType | dashboardLinkType.Link;` but it should be `type: DashboardLinkType`",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "icon": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Icon name to be displayed with the link",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "tooltip": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Tooltip to display when the user hovers their mouse over it",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "url": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Link URL. Only required/valid if the type is link",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "tags": {
+ SchemaProps: spec.SchemaProps{
+ Description: "List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "asDropdown": {
+ SchemaProps: spec.SchemaProps{
+ Description: "If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "targetBlank": {
+ SchemaProps: spec.SchemaProps{
+ Description: "If true, the link will be opened in a new tab",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "includeVars": {
+ SchemaProps: spec.SchemaProps{
+ Description: "If true, includes current template variables values in the link as query params",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "keepTime": {
+ SchemaProps: spec.SchemaProps{
+ Description: "If true, includes current time range in the link as query params",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"title", "type", "icon", "tooltip", "tags", "asDropdown", "targetBlank", "includeVars", "keepTime"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDataLink(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "url": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "targetBlank": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"title", "url"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDataQueryKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The kind of a DataQueryKind is the datasource type",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDataSourceRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The plugin type-id",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Specific datasource instance",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDataTransformerConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Transformations allow to manipulate data returned by a query before the system applies a visualization. Using transformations you can: rename fields, join time series data, perform mathematical operations across queries, use the output of one transformation as the input to another transformation, etc.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Unique identifier of transformer",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "disabled": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Disabled transformations are skipped",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "filter": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Optional frame matcher. When missing it will be applied to all results",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMatcherConfig"),
+ },
+ },
+ "topic": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Where to pull DataFrames from as input to transformation",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Options to be passed to the transformer Valid options depend on the transformer id",
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id", "options"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMatcherConfig"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDatasourceVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Datasource variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDatasourceVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Datasource variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "pluginId": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "refresh": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "regex": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "multi": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "includeAll": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "allValue": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "allowCustomValue": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "pluginId", "refresh", "regex", "current", "options", "multi", "includeAll", "hide", "skipUrlSync", "allowCustomValue"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardDynamicConfigValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardElementReference(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"kind", "name"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardFieldColor(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Map a field to a color.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The main color scheme mode.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "fixedColor": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The fixed color value for fixed or shades color modes.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "seriesBy": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Some visualizations need to know how to assign a series color from by value color schemes.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardFieldConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results. Each column within this structure is called a field. A field can represent a single time series or table column. Field options allow you to change how the data is displayed in your visualizations.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "displayName": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The display value for this field. This supports template variables blank is auto",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "displayNameFromDS": {
+ SchemaProps: spec.SchemaProps{
+ Description: "This can be used by data sources that return and explicit naming structure for values and labels When this property is configured, this value is used rather than the default naming strategy.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Human readable field metadata",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "path": {
+ SchemaProps: spec.SchemaProps{
+ Description: "An explicit path to the field in the datasource. When the frame meta includes a path, This will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and may be used to update the results",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "writeable": {
+ SchemaProps: spec.SchemaProps{
+ Description: "True if data source can write a value to the path. Auth/authz are supported separately",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "filterable": {
+ SchemaProps: spec.SchemaProps{
+ Description: "True if data source field supports ad-hoc filters",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "unit": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Unit a field should use. The unit you select is applied to all fields except time. You can use the units ID availables in Grafana or a custom unit. Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts As custom unit, you can use the following formats: `suffix:` for custom unit that should go after value. `prefix:` for custom unit that should go before value. `time:` For custom date time formats type for example `time:YYYY-MM-DD`. `si:` for custom SI units. For example: `si: mF`. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character. `count:` for a custom count unit. `currency:` for custom a currency unit.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "decimals": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Specify the number of decimals Grafana includes in the rendered value. If you leave this field blank, Grafana automatically truncates the number of decimals based on the value. For example 1.1234 will display as 1.12 and 100.456 will display as 100. To display all decimals, set the unit to `String`.",
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "min": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.",
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "max": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.",
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "mappings": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Convert input values into a display string",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap"),
+ },
+ },
+ },
+ },
+ },
+ "thresholds": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Map numeric values to states",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThresholdsConfig"),
+ },
+ },
+ "color": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Panel color configuration",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldColor"),
+ },
+ },
+ "links": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The behavior when clicking on a result",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "noValue": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Alternative to empty string",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "custom": {
+ SchemaProps: spec.SchemaProps{
+ Description: "custom is specified by the FieldConfig field in panel plugin schemas.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldColor", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThresholdsConfig", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardFieldConfigSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results. Each column within this structure is called a field. A field can represent a single time series or table column. Field options allow you to change how the data is displayed in your visualizations.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "defaults": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Defaults are the options applied to all fields.",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfig"),
+ },
+ },
+ "overrides": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Overrides are the options applied to specific fields overriding the defaults.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2FieldConfigSourceOverrides"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"defaults", "overrides"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfig", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2FieldConfigSourceOverrides"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutItemKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutItemSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "x": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "y": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "width": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "height": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "element": {
+ SchemaProps: spec.SchemaProps{
+ Description: "reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardElementReference"),
+ },
+ },
+ "repeat": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRepeatOptions"),
+ },
+ },
+ },
+ Required: []string{"x", "y", "width", "height", "element"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardElementReference", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRepeatOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "GridLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKind"),
+ },
+ },
+ "AutoGridLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutKind"),
+ },
+ },
+ "TabsLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutKind"),
+ },
+ },
+ "RowsLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutKind"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "GridLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKind"),
+ },
+ },
+ "RowsLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutKind"),
+ },
+ },
+ "AutoGridLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutKind"),
+ },
+ },
+ "TabsLayoutKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutKind"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAutoGridLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGridLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutItemKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGroupByVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Group variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardGroupByVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "GroupBy variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"),
+ },
+ },
+ "defaultValue": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "multi": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "current", "options", "multi", "hide", "skipUrlSync"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardIntervalVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Interval variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardIntervalVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Interval variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "auto": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "auto_min": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "auto_count": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "refresh": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "query", "current", "options", "auto", "auto_min", "auto_count", "refresh", "hide", "skipUrlSync"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardJSONCodec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "DashboardJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding",
+ Type: []string{"object"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKindSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKindSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelKindSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Panel ID for the library panel in the dashboard",
+ Default: 0,
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Title for the library panel in the dashboard",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "libraryPanel": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelRef"),
+ },
+ },
+ },
+ Required: []string{"id", "title", "libraryPanel"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelRef"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardLibraryPanelRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "A library panel is a reusable panel that you can use in any dashboard. When you make a change to a library panel, that change propagates to all instances of where the panel is used. Library panels streamline reuse of panels across multiple dashboards.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Library panel name",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Library panel uid",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "uid"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.Dashboard"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.Dashboard", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardMatcherConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation. It comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The matcher id. This is used to find the matcher implementation from registry.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The matcher options. This is specific to the matcher implementation.",
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "metadata contains embedded CommonMetadata and can be extended with custom string fields without external reference as using the CommonMetadata reference breaks thema codegen.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "updateTimestamp": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "date-time",
+ },
+ },
+ "createdBy": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "creationTimestamp": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "date-time",
+ },
+ },
+ "deletionTimestamp": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "date-time",
+ },
+ },
+ "finalizers": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "resourceVersion": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "generation": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "updatedBy": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "labels": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"updateTimestamp", "createdBy", "uid", "creationTimestamp", "finalizers", "resourceVersion", "generation", "updatedBy", "labels"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardMetricFindValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Define the MetricFindValue type",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "text": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrFloat64"),
+ },
+ },
+ "group": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "expandable": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"text"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrFloat64"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardPanelKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardPanelKindOrLibraryPanelKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "PanelKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKind"),
+ },
+ },
+ "LibraryPanelKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKind"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardPanelQueryKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQuerySpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQuerySpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardPanelQuerySpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind"),
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"),
+ },
+ },
+ "refId": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hidden": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"query", "refId", "hidden"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardPanelSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "links": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataLink"),
+ },
+ },
+ },
+ },
+ },
+ "data": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupKind"),
+ },
+ },
+ "vizConfig": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigKind"),
+ },
+ },
+ "transparent": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id", "title", "description", "links", "data", "vizConfig"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryGroupKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryGroupSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryGroupSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "queries": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQueryKind"),
+ },
+ },
+ },
+ },
+ },
+ "transformations": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTransformationKind"),
+ },
+ },
+ },
+ },
+ },
+ "queryOptions": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryOptionsSpec"),
+ },
+ },
+ },
+ Required: []string{"queries", "transformations", "queryOptions"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryOptionsSpec", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTransformationKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryOptionsSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "timeFrom": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "maxDataPoints": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "timeShift": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "queryCachingTTL": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "interval": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "cacheTimeout": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hideTimeOverride": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Query variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "QueryVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKind"),
+ },
+ },
+ "TextVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableKind"),
+ },
+ },
+ "ConstantVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableKind"),
+ },
+ },
+ "DatasourceVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableKind"),
+ },
+ },
+ "IntervalVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableKind"),
+ },
+ },
+ "CustomVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableKind"),
+ },
+ },
+ "GroupByVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableKind"),
+ },
+ },
+ "AdhocVariableKind": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableKind"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConstantVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardCustomVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDatasourceVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGroupByVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardIntervalVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardQueryVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Query variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "refresh": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef"),
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind"),
+ },
+ },
+ "regex": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "sort": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "definition": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "multi": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "includeAll": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "allValue": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "placeholder": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "allowCustomValue": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "staticOptions": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ },
+ },
+ },
+ "staticOptionsOrder": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "current", "hide", "refresh", "skipUrlSync", "query", "regex", "sort", "options", "multi", "includeAll", "allowCustomValue"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRangeMap(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Range to match against and the result to apply when the value is within the range",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RangeMapOptions"),
+ },
+ },
+ },
+ Required: []string{"type", "options"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RangeMapOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRegexMap(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Regular expression to match against and the result to apply when the value matches the regex",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RegexMapOptions"),
+ },
+ },
+ },
+ Required: []string{"type", "options"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2RegexMapOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "direction": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "maxPerRow": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ },
+ Required: []string{"mode", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRowRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutRowKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutRowSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "collapse": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "hideHeader": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "fillScreen": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "conditionalRendering": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind"),
+ },
+ },
+ "repeat": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowRepeatOptions"),
+ },
+ },
+ "layout": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind"),
+ },
+ },
+ },
+ Required: []string{"layout"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowRepeatOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardRowsLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "rows": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"rows"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRowsLayoutRowKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "annotations": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQueryKind"),
+ },
+ },
+ },
+ },
+ },
+ "cursorSync": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Configuration of dashboard cursor sync behavior. \"Off\" for no shared crosshair or tooltip (default). \"Crosshair\" for shared crosshair. \"Tooltip\" for shared crosshair AND shared tooltip.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Description of dashboard.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "editable": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Whether a dashboard is editable or not.",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "elements": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKindOrLibraryPanelKind"),
+ },
+ },
+ },
+ },
+ },
+ "layout": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind"),
+ },
+ },
+ "links": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Links with references to other dashboards or external websites.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDashboardLink"),
+ },
+ },
+ },
+ },
+ },
+ "liveNow": {
+ SchemaProps: spec.SchemaProps{
+ Description: "When set to true, the dashboard will redraw panels at an interval matching the pixel width. This will keep data \"moving left\" regardless of the query refresh rate. This setting helps avoid dashboards presenting stale live data.",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "preload": {
+ SchemaProps: spec.SchemaProps{
+ Description: "When set to true, the dashboard will load all panels in the dashboard when it's loaded.",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "revision": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Plugins only. The version of the dashboard installed together with the plugin. This is used to determine if the dashboard should be updated when the plugin is updated.",
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ "tags": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Tags associated with dashboard.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "timeSettings": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeSettingsSpec"),
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Title of dashboard.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "variables": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Configured template variables.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"annotations", "cursorSync", "elements", "layout", "links", "preload", "tags", "timeSettings", "title", "variables"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAnnotationQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDashboardLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardPanelKindOrLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeSettingsSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardSpecialValueMap(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2SpecialValueMapOptions"),
+ },
+ },
+ },
+ Required: []string{"type", "options"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardV2alpha2SpecialValueMapOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "conversion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Optional conversion status.",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConversionStatus"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConversionStatus"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardStringOrArrayOfString(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "String": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "ArrayOfString": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardStringOrFloat64(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "String": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "Float64": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTabRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode", "value"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "tabs": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabKind"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"tabs"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabKind"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutTabKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabsLayoutTabSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTabsLayoutTabSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "layout": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind"),
+ },
+ },
+ "conditionalRendering": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind"),
+ },
+ },
+ "repeat": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabRepeatOptions"),
+ },
+ },
+ },
+ Required: []string{"layout"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardConditionalRenderingGroupKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTabRepeatOptions"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTextVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Text variable kind",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTextVariableSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTextVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Text variable specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "current": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"),
+ },
+ },
+ "query": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "label": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "hide": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "skipUrlSync": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "current", "query", "hide", "skipUrlSync"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVariableOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardThreshold(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Default: 0,
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "color": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"value", "color"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardThresholdsConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "steps": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThreshold"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"mode", "steps"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardThreshold"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTimeRangeOption(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "display": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "from": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "to": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"display", "from", "to"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTimeSettingsSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Time configuration It defines the default time config for the time picker, the refresh picker for the specific dashboard.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "timezone": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Timezone of dashboard. Accepted values are IANA TZDB zone ID or \"browser\" or \"utc\".",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "from": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Start time range for dashboard. Accepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "to": {
+ SchemaProps: spec.SchemaProps{
+ Description: "End time range for dashboard. Accepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "autoRefresh": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Refresh rate of dashboard. Represented via interval string, e.g. \"5s\", \"1m\", \"1h\", \"1d\". v1: refresh",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "autoRefreshIntervals": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Interval options available in the refresh picker dropdown. v1: timepicker.refresh_intervals",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "quickRanges": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard. v1: timepicker.quick_ranges , not exposed in the UI",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeRangeOption"),
+ },
+ },
+ },
+ },
+ },
+ "hideTimepicker": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Whether timepicker is visible or not. v1: timepicker.hidden",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "weekStart": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Day when the week starts. Expressed by the name of the day in lowercase, e.g. \"monday\".",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "fiscalYearStartMonth": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The month that the fiscal year starts on. 0 = January, 11 = December",
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "nowDelay": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values. v1: timepicker.nowDelay",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"from", "to", "autoRefresh", "autoRefreshIntervals", "hideTimepicker", "fiscalYearStartMonth"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardTimeRangeOption"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardTransformationKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The kind of a TransformationKind is the transformation ID",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataTransformerConfig"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDataTransformerConfig"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2FieldConfigSourceOverrides(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "matcher": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMatcherConfig"),
+ },
+ },
+ "properties": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDynamicConfigValue"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"matcher", "properties"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardDynamicConfigValue", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardMatcherConfig"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2RangeMapOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "from": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Min value of the range. It can be null which means -Infinity",
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "to": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Max value of the range. It can be null which means +Infinity",
+ Type: []string{"number"},
+ Format: "double",
+ },
+ },
+ "result": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Config to apply when the value is within the range",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"),
+ },
+ },
+ },
+ Required: []string{"from", "to", "result"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2RegexMapOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "pattern": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Regular expression to match against",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "result": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Config to apply when the value matches the regex",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"),
+ },
+ },
+ },
+ Required: []string{"pattern", "result"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardV2alpha2SpecialValueMapOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "match": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Special value to match against",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "result": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Config to apply when the value matches the special value",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"),
+ },
+ },
+ },
+ Required: []string{"match", "result"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardValueMap(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Map with : ValueMappingResult. For example: { \"10\": { text: \"Perfection!\", color: \"green\" } }",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"type", "options"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMappingResult"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "ValueMap": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMap"),
+ },
+ },
+ "RangeMap": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRangeMap"),
+ },
+ },
+ "RegexMap": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRegexMap"),
+ },
+ },
+ "SpecialValueMap": {
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpecialValueMap"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRangeMap", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardRegexMap", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpecialValueMap", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardValueMap"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardValueMappingResult(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Result used as replacement with text and color when the value matches",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "text": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Text to display when the value matches",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "color": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Text to use when the value matches",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "icon": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Icon to display when the value matches. Only specific visualizations.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "index": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Position in the mapping array. Only used internally.",
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardVariableOption(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Variable option specification",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "selected": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Whether the option is selected or not",
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "text": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Text to be displayed for the option",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrArrayOfString"),
+ },
+ },
+ "value": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Value of the option",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrArrayOfString"),
+ },
+ },
+ },
+ Required: []string{"text", "value"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStringOrArrayOfString"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardVersionInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "version": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The internal ID for this version (will be replaced with resourceVersion)",
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ "parentVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "If the dashboard came from a previous version, it is set here",
+ Type: []string{"integer"},
+ Format: "int32",
+ },
+ },
+ "created": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The creation timestamp for this version",
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ "createdBy": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The user who created this version",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "message": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Message passed while saving the version",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"version", "created"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardVersionList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVersionInfo"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVersionInfo", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardVizConfigKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The kind of a VizConfigKind is the plugin ID",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigSpec"),
+ },
+ },
+ },
+ Required: []string{"kind", "spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardVizConfigSpec"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardVizConfigSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "--- Kinds ---",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "pluginVersion": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "fieldConfig": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfigSource"),
+ },
+ },
+ },
+ Required: []string{"pluginVersion", "options", "fieldConfig"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardFieldConfigSource"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_DashboardWithAccessInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "This is like the legacy DTO where access and metadata are all returned in a single call",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the Dashboard",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStatus"),
+ },
+ },
+ "access": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAccess"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status", "access"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardAccess", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardSpec", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.DashboardStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_LibraryPanel(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Standard object's metadata More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Panel properties",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Status will show errors",
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelStatus"),
+ },
+ },
+ },
+ Required: []string{"spec"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelSpec", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanelStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_LibraryPanelList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanel"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2.LibraryPanel", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_LibraryPanelSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The panel type",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "pluginVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The panel type",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The panel title",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Library panel description",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "options": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The options schema depends on the panel type",
+ Ref: ref("github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"),
+ },
+ },
+ "fieldConfig": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The fieldConfig schema depends on the panel type",
+ Ref: ref("github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"),
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The default datasource type",
+ Ref: ref("github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1.DataSourceRef"),
+ },
+ },
+ "targets": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "set",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "The datasource queries",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Ref: ref("github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1.DataQuery"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"type", "options", "fieldConfig"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1.DataQuery", "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1.DataSourceRef", "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_LibraryPanelStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "warnings": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Translation warnings (mostly things that were in SQL columns but not found in the saved body)",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ "missing": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The properties previously stored in SQL that are not included in this model",
+ Ref: ref("github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"),
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"},
+ }
+}
+
+func schema_pkg_apis_dashboard_v2alpha2_VersionsQueryOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "path": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Path is the URL path",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "version": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"integer"},
+ Format: "int64",
+ },
+ },
+ },
+ },
+ },
+ }
+}
diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi_violation_exceptions.list b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi_violation_exceptions.list
new file mode 100644
index 00000000000..1db67fbe438
--- /dev/null
+++ b/apps/dashboard/pkg/apis/dashboard/v2alpha2/zz_generated.openapi_violation_exceptions.list
@@ -0,0 +1,67 @@
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAdHocFilterWithLabels,ValueLabels
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAdHocFilterWithLabels,Values
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAdhocVariableSpec,BaseFilters
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAdhocVariableSpec,DefaultKeys
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAdhocVariableSpec,Filters
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAnnotationPanelFilter,Ids
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardAutoGridLayoutSpec,Items
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardConditionalRenderingGroupSpec,Items
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardCustomVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardDashboardLink,Tags
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardDatasourceVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardFieldConfig,Links
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardFieldConfig,Mappings
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardFieldConfigSource,Overrides
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutSpec,Items
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGroupByVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardIntervalVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardMetadata,Finalizers
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardPanelSpec,Links
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryGroupSpec,Queries
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryGroupSpec,Transformations
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableSpec,Options
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableSpec,StaticOptions
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardRowsLayoutSpec,Rows
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardSpec,Annotations
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardSpec,Links
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardSpec,Tags
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardSpec,Variables
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardStringOrArrayOfString,ArrayOfString
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardTabsLayoutSpec,Tabs
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardThresholdsConfig,Steps
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardTimeSettingsSpec,AutoRefreshIntervals
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardTimeSettingsSpec,QuickRanges
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardV2alpha2FieldConfigSourceOverrides,Properties
+API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,LibraryPanelStatus,Warnings
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingDataKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingTimeRangeSizeKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,AutoGridLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,GridLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,RowsLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,TabsLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind,AutoGridLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind,GridLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind,RowsLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind,TabsLayoutKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardIntervalVariableSpec,AutoCount
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardIntervalVariableSpec,AutoMin
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardPanelKindOrLibraryPanelKind,LibraryPanelKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardPanelKindOrLibraryPanelKind,PanelKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,AdhocVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,ConstantVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,CustomVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,DatasourceVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,GroupByVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,IntervalVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,QueryVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,TextVariableKind
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardStringOrArrayOfString,ArrayOfString
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardStringOrArrayOfString,String
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardStringOrFloat64,Float64
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardStringOrFloat64,String
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,RangeMap
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,RegexMap
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,SpecialValueMap
+API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,ValueMap
+API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2,DashboardList,ListMeta
diff --git a/apps/dashboard/pkg/apis/dashboard_manifest.go b/apps/dashboard/pkg/apis/dashboard_manifest.go
index 568e229d09d..59f0032ab5f 100644
--- a/apps/dashboard/pkg/apis/dashboard_manifest.go
+++ b/apps/dashboard/pkg/apis/dashboard_manifest.go
@@ -14,6 +14,7 @@ import (
v0alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
v1beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
v2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ v2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
)
var appManifestData = app.ManifestData{
@@ -36,6 +37,10 @@ var appManifestData = app.ManifestData{
{
Name: "v2alpha1",
},
+
+ {
+ Name: "v2alpha2",
+ },
},
},
},
@@ -53,6 +58,7 @@ var kindVersionToGoType = map[string]resource.Kind{
"Dashboard/v0alpha1": v0alpha1.DashboardKind(),
"Dashboard/v1beta1": v1beta1.DashboardKind(),
"Dashboard/v2alpha1": v2alpha1.DashboardKind(),
+ "Dashboard/v2alpha2": v2alpha2.DashboardKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
diff --git a/apps/dashboard/pkg/migration/conversion/conversion.go b/apps/dashboard/pkg/migration/conversion/conversion.go
index ff9f1c0365c..8fb35a45dbe 100644
--- a/apps/dashboard/pkg/migration/conversion/conversion.go
+++ b/apps/dashboard/pkg/migration/conversion/conversion.go
@@ -6,167 +6,77 @@ import (
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
- dashv2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
- "github.com/grafana/grafana/apps/dashboard/pkg/migration"
- "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+ dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
)
func RegisterConversions(s *runtime.Scheme) error {
+ // v0 conversions
if err := s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_V0_to_V1(a.(*dashv0.Dashboard), b.(*dashv1.Dashboard), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv2.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_V0_to_V2(a.(*dashv0.Dashboard), b.(*dashv2.Dashboard), scope)
+ if err := s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv2alpha1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V0_to_V2alpha1(a.(*dashv0.Dashboard), b.(*dashv2alpha1.Dashboard), scope)
}); err != nil {
return err
}
+ if err := s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv2alpha2.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V0_to_V2alpha2(a.(*dashv0.Dashboard), b.(*dashv2alpha2.Dashboard), scope)
+ }); err != nil {
+ return err
+ }
+
+ // v1 conversions
if err := s.AddConversionFunc((*dashv1.Dashboard)(nil), (*dashv0.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_V1_to_V0(a.(*dashv1.Dashboard), b.(*dashv0.Dashboard), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*dashv1.Dashboard)(nil), (*dashv2.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_V1_to_V2(a.(*dashv1.Dashboard), b.(*dashv2.Dashboard), scope)
+ if err := s.AddConversionFunc((*dashv1.Dashboard)(nil), (*dashv2alpha1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V1_to_V2alpha1(a.(*dashv1.Dashboard), b.(*dashv2alpha1.Dashboard), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*dashv2.Dashboard)(nil), (*dashv0.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_V2_to_V0(a.(*dashv2.Dashboard), b.(*dashv0.Dashboard), scope)
+ if err := s.AddConversionFunc((*dashv1.Dashboard)(nil), (*dashv2alpha2.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V1_to_V2alpha2(a.(*dashv1.Dashboard), b.(*dashv2alpha2.Dashboard), scope)
}); err != nil {
return err
}
- if err := s.AddConversionFunc((*dashv2.Dashboard)(nil), (*dashv1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
- return Convert_V2_to_V1(a.(*dashv2.Dashboard), b.(*dashv1.Dashboard), scope)
+
+ // v2alpha1 conversions
+ if err := s.AddConversionFunc((*dashv2alpha1.Dashboard)(nil), (*dashv0.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha1_to_V0(a.(*dashv2alpha1.Dashboard), b.(*dashv0.Dashboard), scope)
}); err != nil {
return err
}
- return nil
-}
-
-func Convert_V0_to_V1(in *dashv0.Dashboard, out *dashv1.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- out.Spec.Object = in.Spec.Object
-
- out.Status = dashv1.DashboardStatus{
- Conversion: &dashv1.DashboardConversionStatus{
- StoredVersion: dashv0.VERSION,
- },
+ if err := s.AddConversionFunc((*dashv2alpha1.Dashboard)(nil), (*dashv1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha1_to_V1(a.(*dashv2alpha1.Dashboard), b.(*dashv1.Dashboard), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*dashv2alpha1.Dashboard)(nil), (*dashv2alpha2.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha1_to_V2alpha2(a.(*dashv2alpha1.Dashboard), b.(*dashv2alpha2.Dashboard), scope)
+ }); err != nil {
+ return err
}
- if err := migration.Migrate(out.Spec.Object, schemaversion.LATEST_VERSION); err != nil {
- out.Status.Conversion.Failed = true
- out.Status.Conversion.Error = err.Error()
- }
-
- return nil
-}
-
-func Convert_V0_to_V2(in *dashv0.Dashboard, out *dashv2.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- // TODO (@radiohead): implement V0 to V2 conversion
- // This is the bare minimum conversion that is needed to make the dashboard servable.
-
- if v, ok := in.Spec.Object["title"]; ok {
- if title, ok := v.(string); ok {
- out.Spec.Title = title
- }
- }
-
- // We need to make sure the layout is set to some value, otherwise the JSON marshaling will fail.
- out.Spec.Layout = dashv2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{
- GridLayoutKind: &dashv2.DashboardGridLayoutKind{
- Kind: "GridLayout",
- Spec: dashv2.DashboardGridLayoutSpec{},
- },
- }
-
- out.Status = dashv2.DashboardStatus{
- Conversion: &dashv2.DashboardConversionStatus{
- StoredVersion: dashv0.VERSION,
- Failed: true,
- Error: "backend conversion not yet implemented",
- },
- }
-
- return nil
-}
-
-func Convert_V1_to_V0(in *dashv1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- out.Spec.Object = in.Spec.Object
-
- out.Status = dashv0.DashboardStatus{
- Conversion: &dashv0.DashboardConversionStatus{
- StoredVersion: dashv1.VERSION,
- },
- }
-
- return nil
-}
-
-func Convert_V1_to_V2(in *dashv1.Dashboard, out *dashv2.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- // TODO (@radiohead): implement V1 to V2 conversion
- // This is the bare minimum conversion that is needed to make the dashboard servable.
-
- if v, ok := in.Spec.Object["title"]; ok {
- if title, ok := v.(string); ok {
- out.Spec.Title = title
- }
- }
-
- // We need to make sure the layout is set to some value, otherwise the JSON marshaling will fail.
- out.Spec.Layout = dashv2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{
- GridLayoutKind: &dashv2.DashboardGridLayoutKind{
- Kind: "GridLayout",
- Spec: dashv2.DashboardGridLayoutSpec{},
- },
- }
-
- out.Status = dashv2.DashboardStatus{
- Conversion: &dashv2.DashboardConversionStatus{
- StoredVersion: dashv1.VERSION,
- Failed: true,
- Error: "backend conversion not yet implemented",
- },
- }
-
- return nil
-}
-
-func Convert_V2_to_V0(in *dashv2.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- // TODO: implement V2 to V0 conversion
-
- out.Status = dashv0.DashboardStatus{
- Conversion: &dashv0.DashboardConversionStatus{
- StoredVersion: dashv2.VERSION,
- Failed: true,
- Error: "backend conversion not yet implemented",
- },
- }
-
- return nil
-}
-
-func Convert_V2_to_V1(in *dashv2.Dashboard, out *dashv1.Dashboard, scope conversion.Scope) error {
- out.ObjectMeta = in.ObjectMeta
-
- // TODO: implement V2 to V1 conversion
-
- out.Status = dashv1.DashboardStatus{
- Conversion: &dashv1.DashboardConversionStatus{
- StoredVersion: dashv2.VERSION,
- Failed: true,
- Error: "backend conversion not yet implemented",
- },
+ // v2alpha2 conversions
+ if err := s.AddConversionFunc((*dashv2alpha2.Dashboard)(nil), (*dashv0.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha2_to_V0(a.(*dashv2alpha2.Dashboard), b.(*dashv0.Dashboard), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*dashv2alpha2.Dashboard)(nil), (*dashv1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha2_to_V1(a.(*dashv2alpha2.Dashboard), b.(*dashv1.Dashboard), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddConversionFunc((*dashv2alpha2.Dashboard)(nil), (*dashv2alpha1.Dashboard)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_V2alpha2_to_V2alpha1(a.(*dashv2alpha2.Dashboard), b.(*dashv2alpha1.Dashboard), scope)
+ }); err != nil {
+ return err
}
return nil
diff --git a/apps/dashboard/pkg/migration/conversion/conversion_test.go b/apps/dashboard/pkg/migration/conversion/conversion_test.go
index 9e51322fee1..0efd0ab6205 100644
--- a/apps/dashboard/pkg/migration/conversion/conversion_test.go
+++ b/apps/dashboard/pkg/migration/conversion/conversion_test.go
@@ -11,7 +11,8 @@ import (
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
- dashv2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
"github.com/grafana/grafana/apps/dashboard/pkg/migration"
"github.com/grafana/grafana/apps/dashboard/pkg/migration/testutil"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
@@ -25,7 +26,8 @@ func TestConversionMatrixExist(t *testing.T) {
versions := []v1.Object{
&dashv0.Dashboard{Spec: common.Unstructured{Object: map[string]any{"title": "dashboardV0"}}},
&dashv1.Dashboard{Spec: common.Unstructured{Object: map[string]any{"title": "dashboardV1"}}},
- &dashv2.Dashboard{Spec: dashv2.DashboardSpec{Title: "dashboardV2"}},
+ &dashv2alpha1.Dashboard{Spec: dashv2alpha1.DashboardSpec{Title: "dashboardV2alpha1"}},
+ &dashv2alpha2.Dashboard{Spec: dashv2alpha2.DashboardSpec{Title: "dashboardV2alpha2"}},
}
scheme := runtime.NewScheme()
diff --git a/apps/dashboard/pkg/migration/conversion/v0.go b/apps/dashboard/pkg/migration/conversion/v0.go
new file mode 100644
index 00000000000..94f3d5b57f4
--- /dev/null
+++ b/apps/dashboard/pkg/migration/conversion/v0.go
@@ -0,0 +1,78 @@
+package conversion
+
+import (
+ "k8s.io/apimachinery/pkg/conversion"
+
+ dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
+ dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
+ dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration"
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+)
+
+func Convert_V0_to_V1(in *dashv0.Dashboard, out *dashv1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ out.Spec.Object = in.Spec.Object
+
+ out.Status = dashv1.DashboardStatus{
+ Conversion: &dashv1.DashboardConversionStatus{
+ StoredVersion: dashv0.VERSION,
+ },
+ }
+
+ if err := migration.Migrate(out.Spec.Object, schemaversion.LATEST_VERSION); err != nil {
+ out.Status.Conversion.Failed = true
+ out.Status.Conversion.Error = err.Error()
+ }
+
+ return nil
+}
+
+func Convert_V0_to_V2alpha1(in *dashv0.Dashboard, out *dashv2alpha1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO (@radiohead): implement V0 to V2 conversion
+ // This is the bare minimum conversion that is needed to make the dashboard servable.
+
+ if v, ok := in.Spec.Object["title"]; ok {
+ if title, ok := v.(string); ok {
+ out.Spec.Title = title
+ }
+ }
+
+ // We need to make sure the layout is set to some value, otherwise the JSON marshaling will fail.
+ out.Spec.Layout = dashv2alpha1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{
+ GridLayoutKind: &dashv2alpha1.DashboardGridLayoutKind{
+ Kind: "GridLayout",
+ Spec: dashv2alpha1.DashboardGridLayoutSpec{},
+ },
+ }
+
+ out.Status = dashv2alpha1.DashboardStatus{
+ Conversion: &dashv2alpha1.DashboardConversionStatus{
+ StoredVersion: dashv0.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V0_to_V2alpha2(in *dashv0.Dashboard, out *dashv2alpha2.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V0 to V2alpha2 conversion
+
+ out.Status = dashv2alpha2.DashboardStatus{
+ Conversion: &dashv2alpha2.DashboardConversionStatus{
+ StoredVersion: dashv0.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
diff --git a/apps/dashboard/pkg/migration/conversion/v1.go b/apps/dashboard/pkg/migration/conversion/v1.go
new file mode 100644
index 00000000000..d71d9e40caf
--- /dev/null
+++ b/apps/dashboard/pkg/migration/conversion/v1.go
@@ -0,0 +1,71 @@
+package conversion
+
+import (
+ "k8s.io/apimachinery/pkg/conversion"
+
+ dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
+ dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
+ dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
+)
+
+func Convert_V1_to_V0(in *dashv1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ out.Spec.Object = in.Spec.Object
+
+ out.Status = dashv0.DashboardStatus{
+ Conversion: &dashv0.DashboardConversionStatus{
+ StoredVersion: dashv1.VERSION,
+ },
+ }
+
+ return nil
+}
+
+func Convert_V1_to_V2alpha1(in *dashv1.Dashboard, out *dashv2alpha1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO (@radiohead): implement V1 to V2 conversion
+ // This is the bare minimum conversion that is needed to make the dashboard servable.
+
+ if v, ok := in.Spec.Object["title"]; ok {
+ if title, ok := v.(string); ok {
+ out.Spec.Title = title
+ }
+ }
+
+ // We need to make sure the layout is set to some value, otherwise the JSON marshaling will fail.
+ out.Spec.Layout = dashv2alpha1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{
+ GridLayoutKind: &dashv2alpha1.DashboardGridLayoutKind{
+ Kind: "GridLayout",
+ Spec: dashv2alpha1.DashboardGridLayoutSpec{},
+ },
+ }
+
+ out.Status = dashv2alpha1.DashboardStatus{
+ Conversion: &dashv2alpha1.DashboardConversionStatus{
+ StoredVersion: dashv1.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V1_to_V2alpha2(in *dashv1.Dashboard, out *dashv2alpha2.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V1 to V2alpha2 conversion
+
+ out.Status = dashv2alpha2.DashboardStatus{
+ Conversion: &dashv2alpha2.DashboardConversionStatus{
+ StoredVersion: dashv1.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
diff --git a/apps/dashboard/pkg/migration/conversion/v2.go b/apps/dashboard/pkg/migration/conversion/v2.go
new file mode 100644
index 00000000000..5186f9257e2
--- /dev/null
+++ b/apps/dashboard/pkg/migration/conversion/v2.go
@@ -0,0 +1,105 @@
+package conversion
+
+import (
+ "k8s.io/apimachinery/pkg/conversion"
+
+ dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
+ dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
+ dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
+ dashv2alpha2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha2"
+)
+
+func Convert_V2alpha1_to_V0(in *dashv2alpha1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2 to V0 conversion
+
+ out.Status = dashv0.DashboardStatus{
+ Conversion: &dashv0.DashboardConversionStatus{
+ StoredVersion: dashv2alpha1.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V2alpha1_to_V1(in *dashv2alpha1.Dashboard, out *dashv1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2 to V1 conversion
+
+ out.Status = dashv1.DashboardStatus{
+ Conversion: &dashv1.DashboardConversionStatus{
+ StoredVersion: dashv2alpha1.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V2alpha1_to_V2alpha2(in *dashv2alpha1.Dashboard, out *dashv2alpha2.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2alpha1 to V2alpha2 conversion
+
+ out.Status = dashv2alpha2.DashboardStatus{
+ Conversion: &dashv2alpha2.DashboardConversionStatus{
+ StoredVersion: dashv2alpha1.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+func Convert_V2alpha2_to_V0(in *dashv2alpha2.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2alpha2 to V0 conversion
+
+ out.Status = dashv0.DashboardStatus{
+ Conversion: &dashv0.DashboardConversionStatus{
+ StoredVersion: dashv2alpha2.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V2alpha2_to_V1(in *dashv2alpha2.Dashboard, out *dashv1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2alpha2 to V1 conversion
+
+ out.Status = dashv1.DashboardStatus{
+ Conversion: &dashv1.DashboardConversionStatus{
+ StoredVersion: dashv2alpha2.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
+
+func Convert_V2alpha2_to_V2alpha1(in *dashv2alpha2.Dashboard, out *dashv2alpha1.Dashboard, scope conversion.Scope) error {
+ out.ObjectMeta = in.ObjectMeta
+
+ // TODO: implement V2alpha2 to V2alpha1 conversion
+
+ out.Status = dashv2alpha1.DashboardStatus{
+ Conversion: &dashv2alpha1.DashboardConversionStatus{
+ StoredVersion: dashv2alpha2.VERSION,
+ Failed: true,
+ Error: "backend conversion not yet implemented",
+ },
+ }
+
+ return nil
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/migrations.go b/apps/dashboard/pkg/migration/schemaversion/migrations.go
index aeafd4ab892..3ca5eea83bd 100644
--- a/apps/dashboard/pkg/migration/schemaversion/migrations.go
+++ b/apps/dashboard/pkg/migration/schemaversion/migrations.go
@@ -5,7 +5,7 @@ import (
)
const (
- MIN_VERSION = 32
+ MIN_VERSION = 28
LATEST_VERSION = 41
)
@@ -26,6 +26,10 @@ type DataSourceInfoProvider interface {
func GetMigrations(dsInfoProvider DataSourceInfoProvider) map[int]SchemaVersionMigrationFunc {
return map[int]SchemaVersionMigrationFunc{
+ 29: V29,
+ 30: V30,
+ 31: V31,
+ 32: V32,
33: V33(dsInfoProvider),
34: V34,
35: V35,
diff --git a/apps/dashboard/pkg/migration/schemaversion/v29.go b/apps/dashboard/pkg/migration/schemaversion/v29.go
new file mode 100644
index 00000000000..27ffddcb8fc
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v29.go
@@ -0,0 +1,59 @@
+package schemaversion
+
+// V29 migrates query variables to ensure their refresh property is set to 1 (on dashboard load)
+// if it is not 1 or 2, and clears their options array if present.
+//
+// Example before migration:
+//
+// "templating": {
+// "list": [
+// { "type": "query", "refresh": 0, "options": [{ "text": "A", "value": "A" }] },
+// { "type": "query", "refresh": 2, "options": [{ "text": "B", "value": "B" }] },
+// { "type": "query", "options": [{ "text": "C", "value": "C" }] }
+// ]
+// }
+//
+// Example after migration:
+//
+// "templating": {
+// "list": [
+// { "type": "query", "refresh": 1, "options": [] },
+// { "type": "query", "refresh": 2, "options": [] },
+// { "type": "query", "refresh": 1, "options": [] }
+// ]
+// }
+func V29(dashboard map[string]interface{}) error {
+ dashboard["schemaVersion"] = 29
+
+ templating, ok := dashboard["templating"].(map[string]interface{})
+ if !ok {
+ return nil
+ }
+ list, ok := templating["list"].([]interface{})
+ if !ok {
+ return nil
+ }
+ for _, v := range list {
+ variable, ok := v.(map[string]interface{})
+ if !ok {
+ continue
+ }
+ if variable["type"] != "query" {
+ continue
+ }
+ // Set refresh to 1 if not 1 or 2
+ refresh, hasRefresh := variable["refresh"]
+ refreshInt := 0
+ if r, ok := refresh.(int); ok {
+ refreshInt = r
+ }
+ if !hasRefresh || (refreshInt != 1 && refreshInt != 2) {
+ variable["refresh"] = 1
+ }
+ // Clear options if present
+ if _, hasOptions := variable["options"]; hasOptions {
+ variable["options"] = []interface{}{}
+ }
+ }
+ return nil
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v29_test.go b/apps/dashboard/pkg/migration/schemaversion/v29_test.go
new file mode 100644
index 00000000000..62d3b6a9051
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v29_test.go
@@ -0,0 +1,127 @@
+package schemaversion_test
+
+import (
+ "testing"
+
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+)
+
+func TestV29(t *testing.T) {
+ tests := []migrationTestCase{
+ {
+ name: "query variables get migrated with refresh and options",
+ input: map[string]interface{}{
+ "title": "V29 Query Variables Migration Test Dashboard",
+ "schemaVersion": 28,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "query", "name": "never_refresh_with_options", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}, "refresh": 0},
+ map[string]interface{}{"type": "query", "name": "never_refresh_without_options", "options": []interface{}{}, "refresh": 0},
+ map[string]interface{}{"type": "query", "name": "dashboard_refresh_with_options", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "dashboard_refresh_without_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "timerange_refresh_with_options", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "timerange_refresh_without_options", "options": []interface{}{}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "no_refresh_with_options", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}},
+ map[string]interface{}{"type": "query", "name": "no_refresh_without_options", "options": []interface{}{}},
+ map[string]interface{}{"type": "query", "name": "unknown_refresh_with_options", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}, "refresh": 2001},
+ map[string]interface{}{"type": "query", "name": "unknown_refresh_without_options", "options": []interface{}{}, "refresh": 2001},
+ map[string]interface{}{"type": "custom", "name": "custom", "options": []interface{}{map[string]interface{}{"text": "custom", "value": "custom"}}},
+ map[string]interface{}{"type": "textbox", "name": "textbox", "options": []interface{}{map[string]interface{}{"text": "Hello", "value": "World"}}},
+ map[string]interface{}{"type": "datasource", "name": "datasource", "options": []interface{}{map[string]interface{}{"text": "ds", "value": "ds"}}},
+ map[string]interface{}{"type": "interval", "name": "interval", "options": []interface{}{map[string]interface{}{"text": "1m", "value": "1m"}}},
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V29 Query Variables Migration Test Dashboard",
+ "schemaVersion": 29,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "query", "name": "never_refresh_with_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "never_refresh_without_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "dashboard_refresh_with_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "dashboard_refresh_without_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "timerange_refresh_with_options", "options": []interface{}{}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "timerange_refresh_without_options", "options": []interface{}{}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "no_refresh_with_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "no_refresh_without_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "unknown_refresh_with_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "unknown_refresh_without_options", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "custom", "name": "custom", "options": []interface{}{map[string]interface{}{"text": "custom", "value": "custom"}}},
+ map[string]interface{}{"type": "textbox", "name": "textbox", "options": []interface{}{map[string]interface{}{"text": "Hello", "value": "World"}}},
+ map[string]interface{}{"type": "datasource", "name": "datasource", "options": []interface{}{map[string]interface{}{"text": "ds", "value": "ds"}}},
+ map[string]interface{}{"type": "interval", "name": "interval", "options": []interface{}{map[string]interface{}{"text": "1m", "value": "1m"}}},
+ },
+ },
+ },
+ },
+ {
+ name: "non-query variables remain unchanged",
+ input: map[string]interface{}{
+ "title": "V29 Non-Query Variables Test Dashboard",
+ "schemaVersion": 28,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "custom", "name": "custom", "options": []interface{}{map[string]interface{}{"text": "custom", "value": "custom"}}},
+ map[string]interface{}{"type": "textbox", "name": "textbox", "options": []interface{}{map[string]interface{}{"text": "Hello", "value": "World"}}},
+ map[string]interface{}{"type": "datasource", "name": "datasource", "options": []interface{}{map[string]interface{}{"text": "ds", "value": "ds"}}},
+ map[string]interface{}{"type": "interval", "name": "interval", "options": []interface{}{map[string]interface{}{"text": "1m", "value": "1m"}}},
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V29 Non-Query Variables Test Dashboard",
+ "schemaVersion": 29,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "custom", "name": "custom", "options": []interface{}{map[string]interface{}{"text": "custom", "value": "custom"}}},
+ map[string]interface{}{"type": "textbox", "name": "textbox", "options": []interface{}{map[string]interface{}{"text": "Hello", "value": "World"}}},
+ map[string]interface{}{"type": "datasource", "name": "datasource", "options": []interface{}{map[string]interface{}{"text": "ds", "value": "ds"}}},
+ map[string]interface{}{"type": "interval", "name": "interval", "options": []interface{}{map[string]interface{}{"text": "1m", "value": "1m"}}},
+ },
+ },
+ },
+ },
+ {
+ name: "all query variables should have options removed",
+ input: map[string]interface{}{
+ "title": "V29 Query Variables Options Removal Test Dashboard",
+ "schemaVersion": 28,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "query", "name": "query1", "options": []interface{}{map[string]interface{}{"text": "A", "value": "A"}}},
+ map[string]interface{}{"type": "query", "name": "query2", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query3", "options": []interface{}{map[string]interface{}{"text": "B", "value": "B"}, map[string]interface{}{"text": "C", "value": "C"}}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "query4", "options": []interface{}{map[string]interface{}{"text": "D", "value": "D"}}, "refresh": 0},
+ map[string]interface{}{"type": "query", "name": "query5", "options": []interface{}{map[string]interface{}{"text": "E", "value": "E"}}, "refresh": 2001},
+ map[string]interface{}{"type": "query", "name": "query6", "options": []interface{}{}},
+ map[string]interface{}{"type": "query", "name": "query7", "options": []interface{}{map[string]interface{}{"text": "F", "value": "F"}}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query8", "options": []interface{}{map[string]interface{}{"text": "G", "value": "G"}}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "query9", "options": []interface{}{map[string]interface{}{"text": "H", "value": "H"}}},
+ map[string]interface{}{"type": "query", "name": "query10", "options": []interface{}{map[string]interface{}{"text": "I", "value": "I"}}, "refresh": 999},
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V29 Query Variables Options Removal Test Dashboard",
+ "schemaVersion": 29,
+ "templating": map[string]interface{}{
+ "list": []interface{}{
+ map[string]interface{}{"type": "query", "name": "query1", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query2", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query3", "options": []interface{}{}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "query4", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query5", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query6", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query7", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query8", "options": []interface{}{}, "refresh": 2},
+ map[string]interface{}{"type": "query", "name": "query9", "options": []interface{}{}, "refresh": 1},
+ map[string]interface{}{"type": "query", "name": "query10", "options": []interface{}{}, "refresh": 1},
+ },
+ },
+ },
+ },
+ }
+
+ runMigrationTests(t, tests, schemaversion.V29)
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v30.go b/apps/dashboard/pkg/migration/schemaversion/v30.go
new file mode 100644
index 00000000000..d892abecb50
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v30.go
@@ -0,0 +1,393 @@
+package schemaversion
+
+import (
+ "strconv"
+)
+
+// V30 upgrades value mappings and migrates tooltip options for panels.
+//
+// This migration addresses two key improvements to panel configurations:
+// 1. Value mappings upgrade: Converts legacy value mapping format to the new structured format
+// 2. Tooltip options migration: Renames tooltipOptions to tooltip in specific panel types: timeseries, xychart, xychart2
+//
+// The migration works by:
+// 1. Iterating through all panels in the dashboard, including nested panels in collapsed rows
+// 2. For each panel, upgrading value mappings in fieldConfig.defaults and fieldConfig.overrides
+// 3. Migrating tooltip options for timeseries, xychart, and xychart2 panels
+// 4. Preserving all other panel configurations and options
+//
+// Value Mappings Migration:
+// - Converts legacy mapping types (1 = ValueToText, 2 = RangeToText) to new format
+// - Handles special "null" values by converting them to SpecialValue mappings
+// - Preserves threshold colors when available
+// - Consolidates multiple value mappings into a single ValueToText mapping
+// - Maintains range mappings as separate RangeToText mappings
+//
+// Tooltip Options Migration:
+// - Renames panel.options.tooltipOptions to panel.options.tooltip
+// - Only applies to timeseries, xychart, and xychart2 panel types
+// - Preserves all tooltip configuration options
+//
+// Example value mappings transformation:
+//
+// Before migration:
+//
+// panel: {
+// "fieldConfig": {
+// "defaults": {
+// "mappings": [
+// { "id": 0, "text": "Up", "type": 1, "value": "1" },
+// { "id": 1, "text": "Down", "type": 1, "value": "0" },
+// { "from": "10", "to": "20", "text": "Medium", "type": 2 }
+// ]
+// }
+// }
+// }
+//
+// After migration:
+//
+// panel: {
+// "fieldConfig": {
+// "defaults": {
+// "mappings": [
+// {
+// "type": "value",
+// "options": {
+// "1": { "text": "Up" },
+// "0": { "text": "Down" }
+// }
+// },
+// {
+// "type": "range",
+// "options": {
+// "from": 10,
+// "to": 20,
+// "result": { "text": "Medium" }
+// }
+// }
+// ]
+// }
+// }
+// }
+//
+// Example tooltip options transformation:
+//
+// Before migration:
+//
+// panel: {
+// "type": "timeseries",
+// "options": {
+// "tooltipOptions": { "mode": "multi" }
+// }
+// }
+//
+// After migration:
+//
+// panel: {
+// "type": "timeseries",
+// "options": {
+// "tooltip": { "mode": "multi" }
+// }
+// }
+func V30(dashboard map[string]interface{}) error {
+ dashboard["schemaVersion"] = 30
+
+ panels, ok := dashboard["panels"].([]interface{})
+ if !ok {
+ return nil
+ }
+
+ for _, panel := range panels {
+ panelMap, ok := panel.(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ upgradeValueMappingsForPanel(panelMap)
+ migrateTooltipOptions(panelMap)
+
+ // Handle nested panels in collapsed rows
+ nestedPanels, hasNested := panelMap["panels"].([]interface{})
+ if !hasNested {
+ continue
+ }
+
+ for _, nestedPanel := range nestedPanels {
+ nestedPanelMap, ok := nestedPanel.(map[string]interface{})
+ if !ok {
+ continue
+ }
+ upgradeValueMappingsForPanel(nestedPanelMap)
+ migrateTooltipOptions(nestedPanelMap)
+ }
+ }
+
+ return nil
+}
+
+// upgradeValueMappingsForPanel migrates value mappings from old format to new format
+func upgradeValueMappingsForPanel(panel map[string]interface{}) {
+ fieldConfig, ok := panel["fieldConfig"].(map[string]interface{})
+ if !ok {
+ return
+ }
+
+ // Upgrade defaults mappings
+ if defaults, ok := fieldConfig["defaults"].(map[string]interface{}); ok {
+ if mappings, ok := defaults["mappings"].([]interface{}); ok {
+ var thresholds map[string]interface{}
+ if t, ok := defaults["thresholds"].(map[string]interface{}); ok {
+ thresholds = t
+ }
+ defaults["mappings"] = upgradeValueMappings(mappings, thresholds)
+ }
+ }
+
+ // Upgrade overrides mappings
+ overrides, hasOverrides := fieldConfig["overrides"].([]interface{})
+ if !hasOverrides {
+ return
+ }
+
+ for _, override := range overrides {
+ overrideMap, ok := override.(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ properties, hasProperties := overrideMap["properties"].([]interface{})
+ if !hasProperties {
+ continue
+ }
+
+ for _, property := range properties {
+ propertyMap, ok := property.(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ if propertyMap["id"] != "mappings" {
+ continue
+ }
+
+ mappings, ok := propertyMap["value"].([]interface{})
+ if !ok {
+ continue
+ }
+
+ propertyMap["value"] = upgradeValueMappings(mappings, nil)
+ }
+ }
+}
+
+// upgradeValueMappings converts legacy value mappings to new format
+func upgradeValueMappings(oldMappings []interface{}, thresholds map[string]interface{}) []interface{} {
+ if len(oldMappings) == 0 {
+ return oldMappings
+ }
+
+ valueMaps := map[string]interface{}{
+ "type": "value",
+ "options": map[string]interface{}{},
+ }
+
+ var newMappings []interface{}
+ hasValueMappings := false
+
+ for _, mapping := range oldMappings {
+ if mappingMap, ok := mapping.(map[string]interface{}); ok {
+ // Check if this is already the new format
+ if mappingType, ok := mappingMap["type"].(string); ok && mappingType != "" {
+ if mappingType == "value" {
+ // Consolidate existing value mappings
+ if options, ok := mappingMap["options"].(map[string]interface{}); ok {
+ valueMapsOptions := valueMaps["options"].(map[string]interface{})
+ for k, v := range options {
+ valueMapsOptions[k] = v
+ }
+ hasValueMappings = true
+ }
+ } else {
+ newMappings = append(newMappings, mappingMap)
+ }
+ continue
+ }
+
+ // Handle legacy format
+ var color interface{}
+ if thresholds != nil {
+ // Try to get color from threshold based on the mapping value
+ if value, ok := mappingMap["value"]; ok {
+ if valueStr, ok := value.(string); ok {
+ if numeric, err := strconv.ParseFloat(valueStr, 64); err == nil {
+ color = getActiveThresholdColor(numeric, thresholds)
+ }
+ }
+ }
+ // For range mappings, use the 'from' value to determine color
+ if fromVal, ok := mappingMap["from"]; ok {
+ if fromStr, ok := fromVal.(string); ok {
+ if numeric, err := strconv.ParseFloat(fromStr, 64); err == nil {
+ color = getActiveThresholdColor(numeric, thresholds)
+ }
+ }
+ }
+ }
+
+ // Convert legacy type numbers to new format
+ if mappingType, ok := mappingMap["type"].(float64); ok {
+ switch int(mappingType) {
+ case 1: // ValueToText
+ if value, ok := mappingMap["value"]; ok {
+ if valueStr, ok := value.(string); ok && valueStr == "null" {
+ // Handle null values as special value mapping
+ // For null values, use the base threshold color (lowest step)
+ if thresholds != nil {
+ color = getBaseThresholdColor(thresholds)
+ }
+ newMappings = append(newMappings, map[string]interface{}{
+ "type": "special",
+ "options": map[string]interface{}{
+ "match": "null",
+ "result": map[string]interface{}{
+ "text": mappingMap["text"],
+ "color": color,
+ },
+ },
+ })
+ } else {
+ // Regular value mapping
+ valueMapsOptions := valueMaps["options"].(map[string]interface{})
+ result := map[string]interface{}{
+ "text": mappingMap["text"],
+ }
+ if color != nil {
+ result["color"] = color
+ }
+ valueMapsOptions[stringifyValue(value)] = result
+ hasValueMappings = true
+ }
+ }
+ case 2: // RangeToText
+ result := map[string]interface{}{
+ "text": mappingMap["text"],
+ }
+ if color != nil {
+ result["color"] = color
+ }
+
+ from, _ := strconv.ParseFloat(stringifyValue(mappingMap["from"]), 64)
+ to, _ := strconv.ParseFloat(stringifyValue(mappingMap["to"]), 64)
+
+ newMappings = append(newMappings, map[string]interface{}{
+ "type": "range",
+ "options": map[string]interface{}{
+ "from": from,
+ "to": to,
+ "result": result,
+ },
+ })
+ }
+ }
+ }
+ }
+
+ // Add consolidated value mappings at the beginning if any exist
+ if hasValueMappings {
+ newMappings = append([]interface{}{valueMaps}, newMappings...)
+ }
+
+ return newMappings
+}
+
+// getActiveThresholdColor returns the color for a value based on thresholds
+func getActiveThresholdColor(value float64, thresholds map[string]interface{}) interface{} {
+ if steps, ok := thresholds["steps"].([]interface{}); ok {
+ var activeStep map[string]interface{}
+
+ for _, step := range steps {
+ if stepMap, ok := step.(map[string]interface{}); ok {
+ if stepValue, ok := stepMap["value"]; ok {
+ if stepValue == nil {
+ // Null value represents negative infinity - this is always the base color
+ activeStep = stepMap
+ continue
+ }
+
+ if stepNum, ok := stepValue.(float64); ok {
+ if value >= stepNum {
+ activeStep = stepMap
+ }
+ }
+ }
+ }
+ }
+
+ if activeStep != nil {
+ return activeStep["color"]
+ }
+ }
+
+ return nil
+}
+
+// getBaseThresholdColor returns the base threshold color (first step with null value)
+func getBaseThresholdColor(thresholds map[string]interface{}) interface{} {
+ if steps, ok := thresholds["steps"].([]interface{}); ok {
+ for _, step := range steps {
+ if stepMap, ok := step.(map[string]interface{}); ok {
+ if stepValue, ok := stepMap["value"]; ok {
+ if stepValue == nil {
+ // This is the base color (null value step)
+ return stepMap["color"]
+ }
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+// migrateTooltipOptions renames tooltipOptions to tooltip for specific panel types
+func migrateTooltipOptions(panel map[string]interface{}) {
+ panelType, ok := panel["type"].(string)
+ if !ok {
+ return
+ }
+
+ // Only migrate for specific panel types
+ if panelType != "timeseries" && panelType != "xychart" && panelType != "xychart2" {
+ return
+ }
+
+ options, ok := panel["options"].(map[string]interface{})
+ if !ok {
+ return
+ }
+
+ tooltipOptions, ok := options["tooltipOptions"]
+ if !ok {
+ return
+ }
+
+ // Rename tooltipOptions to tooltip
+ options["tooltip"] = tooltipOptions
+ delete(options, "tooltipOptions")
+}
+
+// stringifyValue converts a value to string
+func stringifyValue(value interface{}) string {
+ switch v := value.(type) {
+ case string:
+ return v
+ case float64:
+ return strconv.FormatFloat(v, 'f', -1, 64)
+ case int:
+ return strconv.Itoa(v)
+ case bool:
+ return strconv.FormatBool(v)
+ default:
+ return ""
+ }
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v30_test.go b/apps/dashboard/pkg/migration/schemaversion/v30_test.go
new file mode 100644
index 00000000000..bbae0e9a412
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v30_test.go
@@ -0,0 +1,499 @@
+package schemaversion_test
+
+import (
+ "testing"
+
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+)
+
+func TestV30(t *testing.T) {
+ tests := []migrationTestCase{
+ {
+ name: "panel with legacy value mappings gets upgraded to new format",
+ input: map[string]interface{}{
+ "title": "V30 Value Mappings Migration Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with legacy value mappings",
+ "id": 1,
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "thresholds": map[string]interface{}{
+ "mode": "absolute",
+ "steps": []interface{}{
+ map[string]interface{}{
+ "color": "green",
+ "value": nil,
+ },
+ map[string]interface{}{
+ "color": "red",
+ "value": float64(80),
+ },
+ },
+ },
+ "mappings": []interface{}{
+ map[string]interface{}{
+ "id": 0,
+ "text": "Up",
+ "type": float64(1),
+ "value": "1",
+ },
+ map[string]interface{}{
+ "id": 1,
+ "text": "Down",
+ "type": float64(1),
+ "value": "0",
+ },
+ map[string]interface{}{
+ "from": "10",
+ "to": "20",
+ "text": "Medium",
+ "type": float64(2),
+ },
+ map[string]interface{}{
+ "type": float64(1),
+ "value": "null",
+ "text": "Null Value",
+ },
+ },
+ },
+ "overrides": []interface{}{
+ map[string]interface{}{
+ "matcher": map[string]interface{}{
+ "id": "byName",
+ "options": "test-field",
+ },
+ "properties": []interface{}{
+ map[string]interface{}{
+ "id": "mappings",
+ "value": []interface{}{
+ map[string]interface{}{
+ "id": 0,
+ "text": "Override Up",
+ "type": float64(1),
+ "value": "1",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 Value Mappings Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with legacy value mappings",
+ "id": 1,
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "thresholds": map[string]interface{}{
+ "mode": "absolute",
+ "steps": []interface{}{
+ map[string]interface{}{
+ "color": "green",
+ "value": nil,
+ },
+ map[string]interface{}{
+ "color": "red",
+ "value": float64(80),
+ },
+ },
+ },
+ "mappings": []interface{}{
+ map[string]interface{}{
+ "type": "value",
+ "options": map[string]interface{}{
+ "1": map[string]interface{}{
+ "text": "Up",
+ "color": "green",
+ },
+ "0": map[string]interface{}{
+ "text": "Down",
+ "color": "green",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "range",
+ "options": map[string]interface{}{
+ "from": float64(10),
+ "to": float64(20),
+ "result": map[string]interface{}{
+ "text": "Medium",
+ "color": "green",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "special",
+ "options": map[string]interface{}{
+ "match": "null",
+ "result": map[string]interface{}{
+ "text": "Null Value",
+ "color": "green",
+ },
+ },
+ },
+ },
+ },
+ "overrides": []interface{}{
+ map[string]interface{}{
+ "matcher": map[string]interface{}{
+ "id": "byName",
+ "options": "test-field",
+ },
+ "properties": []interface{}{
+ map[string]interface{}{
+ "id": "mappings",
+ "value": []interface{}{
+ map[string]interface{}{
+ "type": "value",
+ "options": map[string]interface{}{
+ "1": map[string]interface{}{
+ "text": "Override Up",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with tooltip options gets migrated to tooltip",
+ input: map[string]interface{}{
+ "title": "V30 Tooltip Options Migration Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with tooltipOptions",
+ "id": 1,
+ "options": map[string]interface{}{
+ "tooltipOptions": map[string]interface{}{
+ "mode": "multi",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "xychart",
+ "title": "XY Chart with tooltipOptions",
+ "id": 2,
+ "options": map[string]interface{}{
+ "tooltipOptions": map[string]interface{}{
+ "mode": "single",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "xychart2",
+ "title": "XY Chart2 with tooltipOptions",
+ "id": 3,
+ "options": map[string]interface{}{
+ "tooltipOptions": map[string]interface{}{
+ "mode": "single",
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 Tooltip Options Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with tooltipOptions",
+ "id": 1,
+ "options": map[string]interface{}{
+ "tooltip": map[string]interface{}{
+ "mode": "multi",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "xychart",
+ "title": "XY Chart with tooltipOptions",
+ "id": 2,
+ "options": map[string]interface{}{
+ "tooltip": map[string]interface{}{
+ "mode": "single",
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "xychart2",
+ "title": "XY Chart2 with tooltipOptions",
+ "id": 3,
+ "options": map[string]interface{}{
+ "tooltip": map[string]interface{}{
+ "mode": "single",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with nested panels in collapsed row gets migrated",
+ input: map[string]interface{}{
+ "title": "V30 Nested Panels Migration Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "row",
+ "title": "Collapsed Row",
+ "id": 1,
+ "collapsed": true,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel with tooltipOptions",
+ "id": 2,
+ "options": map[string]interface{}{
+ "tooltipOptions": map[string]interface{}{
+ "mode": "multi",
+ },
+ },
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "mappings": []interface{}{
+ map[string]interface{}{
+ "id": 0,
+ "text": "On",
+ "type": float64(1),
+ "value": "1",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 Nested Panels Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "row",
+ "title": "Collapsed Row",
+ "id": 1,
+ "collapsed": true,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel with tooltipOptions",
+ "id": 2,
+ "options": map[string]interface{}{
+ "tooltip": map[string]interface{}{
+ "mode": "multi",
+ },
+ },
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "mappings": []interface{}{
+ map[string]interface{}{
+ "type": "value",
+ "options": map[string]interface{}{
+ "1": map[string]interface{}{
+ "text": "On",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with no mappings or tooltip options remains unchanged",
+ input: map[string]interface{}{
+ "title": "V30 No Changes Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with no relevant configurations",
+ "id": 1,
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "unit": "bytes",
+ },
+ },
+ "options": map[string]interface{}{
+ "legend": map[string]interface{}{
+ "displayMode": "list",
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 No Changes Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with no relevant configurations",
+ "id": 1,
+ "fieldConfig": map[string]interface{}{
+ "defaults": map[string]interface{}{
+ "unit": "bytes",
+ },
+ },
+ "options": map[string]interface{}{
+ "legend": map[string]interface{}{
+ "displayMode": "list",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panels remain unchanged when no V30 specific migrations apply",
+ input: map[string]interface{}{
+ "title": "V30 Panel Types Unchanged Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph panel",
+ "id": 1,
+ },
+ map[string]interface{}{
+ "type": "singlestat",
+ "title": "Singlestat panel",
+ "id": 2,
+ },
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Already timeseries panel",
+ "id": 3,
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 Panel Types Unchanged Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph panel",
+ "id": 1,
+ },
+ map[string]interface{}{
+ "type": "singlestat",
+ "title": "Singlestat panel",
+ "id": 2,
+ },
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Already timeseries panel",
+ "id": 3,
+ },
+ },
+ },
+ },
+ {
+ name: "graph panels with different configurations remain unchanged in V30",
+ input: map[string]interface{}{
+ "title": "V30 Graph Panel Configurations Test Dashboard",
+ "schemaVersion": 29,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with series mode and legend values",
+ "id": 1,
+ "xaxis": map[string]interface{}{
+ "mode": "series",
+ },
+ "legend": map[string]interface{}{
+ "values": true,
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with series mode",
+ "id": 2,
+ "xaxis": map[string]interface{}{
+ "mode": "series",
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with histogram mode",
+ "id": 3,
+ "xaxis": map[string]interface{}{
+ "mode": "histogram",
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with default configuration",
+ "id": 4,
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V30 Graph Panel Configurations Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with series mode and legend values",
+ "id": 1,
+ "xaxis": map[string]interface{}{
+ "mode": "series",
+ },
+ "legend": map[string]interface{}{
+ "values": true,
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with series mode",
+ "id": 2,
+ "xaxis": map[string]interface{}{
+ "mode": "series",
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with histogram mode",
+ "id": 3,
+ "xaxis": map[string]interface{}{
+ "mode": "histogram",
+ },
+ },
+ map[string]interface{}{
+ "type": "graph",
+ "title": "Graph with default configuration",
+ "id": 4,
+ },
+ },
+ },
+ },
+ }
+
+ runMigrationTests(t, tests, schemaversion.V30)
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v31.go b/apps/dashboard/pkg/migration/schemaversion/v31.go
new file mode 100644
index 00000000000..3b4c907ce5d
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v31.go
@@ -0,0 +1,132 @@
+package schemaversion
+
+// V31 adds a merge transformer after any labelsToFields transformer in panel transformations.
+//
+// This migration addresses data processing workflow optimization by automatically inserting
+// a merge transformation after the labelsToFields transformation. When the labelsToFields
+// transformer converts time series labels to individual fields, it can result in multiple
+// data frames that need to be consolidated for proper visualization and analysis.
+//
+// The migration works by:
+// 1. Iterating through all panels in the dashboard, including nested panels in collapsed rows
+// 2. Examining the transformations array within each panel
+// 3. Identifying transformations with id 'labelsToFields'
+// 4. Inserting a merge transformation with empty options immediately after each labelsToFields transformation
+// 5. Preserving the original labelsToFields options (mode, keepLabels, valueLabel, etc.) without modification
+// 6. Using empty options for merge transformations to enable optimal default consolidation behavior
+// 7. Preserving the original order and configuration of all other transformations
+//
+// The migration handles complex scenarios including:
+// - Multiple labelsToFields transformations within a single panel
+// - Panels with mixed transformation types
+// - Nested panels within collapsed row panels
+// - Panels with no transformations (left unchanged)
+// - Panels with transformations but no labelsToFields (left unchanged)
+//
+// Example transformation:
+//
+// Before migration:
+//
+// panel: {
+// "transformations": [
+// { "id": "organize", "options": {} },
+// { "id": "labelsToFields", "options": {} },
+// { "id": "calculateField", "options": {} },
+// { "id": "labelsToFields", "options": { "mode": "rows", "keepLabels": ["job", "instance"] } },
+// ]
+// }
+//
+// After migration:
+//
+// panel: {
+// "transformations": [
+// { "id": "organize", "options": {} },
+// { "id": "labelsToFields", "options": {} },
+// { "id": "merge", "options": {} },
+// { "id": "calculateField", "options": {} },
+// { "id": "labelsToFields", "options": { "mode": "rows", "keepLabels": ["job", "instance"] } },
+// { "id": "merge", "options": {} }
+// ]
+// }
+func V31(dashboard map[string]interface{}) error {
+ dashboard["schemaVersion"] = int(31)
+
+ panels, ok := dashboard["panels"].([]interface{})
+ if !ok {
+ return nil
+ }
+
+ // Process all panels, including nested ones
+ processPanelsV31(panels)
+
+ return nil
+}
+
+// processPanelsV31 recursively processes panels, including nested panels within rows
+func processPanelsV31(panels []interface{}) {
+ for _, panel := range panels {
+ p, ok := panel.(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ // Process nested panels if this is a row panel
+ if p["type"] == "row" {
+ nestedPanels, hasNested := p["panels"].([]interface{})
+ if !hasNested {
+ continue
+ }
+ processPanelsV31(nestedPanels)
+ continue
+ }
+
+ transformations, ok := p["transformations"].([]interface{})
+ if !ok {
+ continue
+ }
+
+ // Check if we have any labelsToFields transformations
+ hasLabelsToFields := false
+ for _, transformation := range transformations {
+ t, ok := transformation.(map[string]interface{})
+ if !ok {
+ continue
+ }
+ if t["id"] == "labelsToFields" {
+ hasLabelsToFields = true
+ break
+ }
+ }
+
+ if !hasLabelsToFields {
+ continue
+ }
+
+ // Create new transformations array with merge transformations added
+ newTransformations := []interface{}{}
+
+ for _, transformation := range transformations {
+ t, ok := transformation.(map[string]interface{})
+ if !ok {
+ newTransformations = append(newTransformations, transformation)
+ continue
+ }
+
+ // Add the current transformation (preserving all original options)
+ newTransformations = append(newTransformations, transformation)
+
+ // If this is a labelsToFields transformation, add a merge transformation after it
+ // with empty options to enable optimal default consolidation behavior
+ if t["id"] == "labelsToFields" {
+ mergeTransformation := map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ }
+ newTransformations = append(newTransformations, mergeTransformation)
+ }
+ }
+
+ // Update the panel with the new transformations
+ p["transformations"] = newTransformations
+ }
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v31_test.go b/apps/dashboard/pkg/migration/schemaversion/v31_test.go
new file mode 100644
index 00000000000..e12040585de
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v31_test.go
@@ -0,0 +1,336 @@
+package schemaversion_test
+
+import (
+ "testing"
+
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+)
+
+func TestV31(t *testing.T) {
+ tests := []migrationTestCase{
+ {
+ name: "panel with basic labelsToFields transformation gets merge transformation added",
+ input: map[string]interface{}{
+ "title": "V31 LabelsToFields Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with basic labelsToFields",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 LabelsToFields Migration Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with basic labelsToFields",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with labelsToFields options preserved during migration",
+ input: map[string]interface{}{
+ "title": "V31 LabelsToFields Options Preservation Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with labelsToFields options",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{
+ "mode": "rows",
+ "keepLabels": []interface{}{"job", "instance"},
+ "valueLabel": "value",
+ },
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 LabelsToFields Options Preservation Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with labelsToFields options",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{
+ "mode": "rows",
+ "keepLabels": []interface{}{"job", "instance"},
+ "valueLabel": "value",
+ },
+ },
+ map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with multiple labelsToFields transformations",
+ input: map[string]interface{}{
+ "title": "V31 Multiple LabelsToFields Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with multiple labelsToFields",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "calculateField",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{
+ "mode": "rows",
+ },
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 Multiple LabelsToFields Migration Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with multiple labelsToFields",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "calculateField",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{
+ "mode": "rows",
+ },
+ },
+ map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "panel with no transformations remains unchanged",
+ input: map[string]interface{}{
+ "title": "V31 No Transformations Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with no transformations",
+ "id": 1,
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 No Transformations Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with no transformations",
+ "id": 1,
+ },
+ },
+ },
+ },
+ {
+ name: "panel with transformations but no labelsToFields remains unchanged",
+ input: map[string]interface{}{
+ "title": "V31 Other Transformations Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with other transformations",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "reduce",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 Other Transformations Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel with other transformations",
+ "id": 1,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "reduce",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "nested panels in row with labelsToFields transformation",
+ input: map[string]interface{}{
+ "title": "V31 Nested Panels Test Dashboard",
+ "schemaVersion": 30,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "row",
+ "title": "Row with nested panels",
+ "id": 1,
+ "collapsed": false,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel with labelsToFields",
+ "id": 2,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel without labelsToFields",
+ "id": 3,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V31 Nested Panels Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "row",
+ "title": "Row with nested panels",
+ "id": 1,
+ "collapsed": false,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel with labelsToFields",
+ "id": 2,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "labelsToFields",
+ "options": map[string]interface{}{},
+ },
+ map[string]interface{}{
+ "id": "merge",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Nested panel without labelsToFields",
+ "id": 3,
+ "transformations": []interface{}{
+ map[string]interface{}{
+ "id": "organize",
+ "options": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "dashboard with no panels",
+ input: map[string]interface{}{
+ "title": "V31 No Panels Test Dashboard",
+ "schemaVersion": 30,
+ },
+ expected: map[string]interface{}{
+ "title": "V31 No Panels Test Dashboard",
+ "schemaVersion": 31,
+ },
+ },
+ }
+ runMigrationTests(t, tests, schemaversion.V31)
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v32.go b/apps/dashboard/pkg/migration/schemaversion/v32.go
new file mode 100644
index 00000000000..6ea48bf0a73
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v32.go
@@ -0,0 +1,27 @@
+package schemaversion
+
+// V32 is a no-op migration that serves as a placeholder for consistency.
+//
+// The migration performs no modifications to the dashboard structure and simply
+// updates the schema version number.
+// Example (no changes made):
+//
+// Before migration:
+//
+// dashboard: {
+// "title": "My Dashboard",
+// "schemaVersion": 31,
+// "panels": [...]
+// }
+//
+// After migration:
+//
+// dashboard: {
+// "title": "My Dashboard",
+// "schemaVersion": 32,
+// "panels": [...] // unchanged
+// }
+func V32(dashboard map[string]interface{}) error {
+ dashboard["schemaVersion"] = int(32)
+ return nil
+}
diff --git a/apps/dashboard/pkg/migration/schemaversion/v32_test.go b/apps/dashboard/pkg/migration/schemaversion/v32_test.go
new file mode 100644
index 00000000000..23df4b26d28
--- /dev/null
+++ b/apps/dashboard/pkg/migration/schemaversion/v32_test.go
@@ -0,0 +1,38 @@
+package schemaversion_test
+
+import (
+ "testing"
+
+ "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
+)
+
+func TestV32(t *testing.T) {
+ tests := []migrationTestCase{
+ {
+ name: "v32 no-op migration updates schema version only",
+ input: map[string]interface{}{
+ "title": "V32 No-Op Migration Test Dashboard",
+ "schemaVersion": 31,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel remains unchanged",
+ "id": 1,
+ },
+ },
+ },
+ expected: map[string]interface{}{
+ "title": "V32 No-Op Migration Test Dashboard",
+ "schemaVersion": 32,
+ "panels": []interface{}{
+ map[string]interface{}{
+ "type": "timeseries",
+ "title": "Panel remains unchanged",
+ "id": 1,
+ },
+ },
+ },
+ },
+ }
+ runMigrationTests(t, tests, schemaversion.V32)
+}
diff --git a/apps/dashboard/pkg/migration/testdata/input/v29.query_variables_refresh_and_options.json b/apps/dashboard/pkg/migration/testdata/input/v29.query_variables_refresh_and_options.json
new file mode 100644
index 00000000000..00bf06ad0c0
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/input/v29.query_variables_refresh_and_options.json
@@ -0,0 +1,137 @@
+{
+ "title": "V29 Query Variables Refresh and Options Migration Test Dashboard",
+ "schemaVersion": 28,
+ "templating": {
+ "list": [
+ {
+ "name": "never_refresh_with_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [
+ {"text": "A", "value": "A"},
+ {"text": "B", "value": "B"}
+ ],
+ "refresh": 0
+ },
+ {
+ "name": "never_refresh_without_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [],
+ "refresh": 0
+ },
+ {
+ "name": "dashboard_refresh_with_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [
+ {"text": "C", "value": "C"}
+ ],
+ "refresh": 1
+ },
+ {
+ "name": "dashboard_refresh_without_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [],
+ "refresh": 1
+ },
+ {
+ "name": "timerange_refresh_with_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [
+ {"text": "D", "value": "D"},
+ {"text": "E", "value": "E"}
+ ],
+ "refresh": 2
+ },
+ {
+ "name": "timerange_refresh_without_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [],
+ "refresh": 2
+ },
+ {
+ "name": "no_refresh_with_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [
+ {"text": "F", "value": "F"}
+ ]
+ },
+ {
+ "name": "no_refresh_without_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": []
+ },
+ {
+ "name": "unknown_refresh_with_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [
+ {"text": "G", "value": "G"}
+ ],
+ "refresh": 2001
+ },
+ {
+ "name": "unknown_refresh_without_options",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": [],
+ "refresh": 2001
+ },
+ {
+ "name": "custom_variable",
+ "type": "custom",
+ "options": [
+ {"text": "custom", "value": "custom"}
+ ]
+ },
+ {
+ "name": "textbox_variable",
+ "type": "textbox",
+ "options": [
+ {"text": "Hello", "value": "World"}
+ ]
+ },
+ {
+ "name": "datasource_variable",
+ "type": "datasource",
+ "options": [
+ {"text": "ds", "value": "ds"}
+ ]
+ },
+ {
+ "name": "interval_variable",
+ "type": "interval",
+ "options": [
+ {"text": "1m", "value": "1m"}
+ ]
+ }
+ ]
+ },
+ "panels": [
+ {
+ "id": 1,
+ "title": "Test Panel",
+ "type": "timeseries",
+ "datasource": "prometheus",
+ "targets": [
+ {
+ "refId": "A",
+ "expr": "up"
+ }
+ ]
+ }
+ ],
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
+ }
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/input/v30.value_mappings_and_tooltip_options.json b/apps/dashboard/pkg/migration/testdata/input/v30.value_mappings_and_tooltip_options.json
new file mode 100644
index 00000000000..672a88ed0b6
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/input/v30.value_mappings_and_tooltip_options.json
@@ -0,0 +1,214 @@
+{
+ "title": "V30 Value Mappings and Tooltip Options Migration Test Dashboard",
+ "schemaVersion": 29,
+ "panels": [
+ {
+ "type": "timeseries",
+ "title": "Panel with legacy value mappings and tooltip options",
+ "id": 1,
+ "fieldConfig": {
+ "defaults": {
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "mappings": [
+ {
+ "id": 0,
+ "text": "Up",
+ "type": 1,
+ "value": "1"
+ },
+ {
+ "id": 1,
+ "text": "Down",
+ "type": 1,
+ "value": "0"
+ },
+ {
+ "from": "10",
+ "to": "20",
+ "text": "Medium",
+ "type": 2
+ },
+ {
+ "type": 1,
+ "value": "null",
+ "text": "Null Value"
+ }
+ ]
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "test-field"
+ },
+ "properties": [
+ {
+ "id": "mappings",
+ "value": [
+ {
+ "id": 0,
+ "text": "Override Up",
+ "type": 1,
+ "value": "1"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "options": {
+ "tooltipOptions": {
+ "mode": "multi"
+ }
+ }
+ },
+ {
+ "type": "xychart",
+ "title": "XY Chart with tooltip options only",
+ "id": 2,
+ "options": {
+ "tooltipOptions": {
+ "mode": "single"
+ }
+ }
+ },
+ {
+ "type": "xychart2",
+ "title": "XY Chart2 with tooltip options",
+ "id": 3,
+ "options": {
+ "tooltipOptions": {
+ "mode": "single",
+ "sort": "none"
+ }
+ }
+ },
+ {
+ "type": "graph",
+ "title": "Graph panel gets migrated to timeseries and tooltip",
+ "id": 4,
+ "options": {
+ "tooltip": {
+ "mode": "single"
+ }
+ }
+ },
+ {
+ "type": "stat",
+ "title": "Panel with complex value mappings",
+ "id": 5,
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "id": 0,
+ "text": "Critical",
+ "type": 1,
+ "value": "100"
+ },
+ {
+ "from": "50",
+ "to": "99",
+ "text": "Warning",
+ "type": 2
+ },
+ {
+ "from": "0",
+ "to": "49",
+ "text": "OK",
+ "type": 2
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "row",
+ "title": "Collapsed Row with nested panels",
+ "id": 6,
+ "collapsed": true,
+ "panels": [
+ {
+ "type": "timeseries",
+ "title": "Nested panel with both migrations",
+ "id": 7,
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "id": 0,
+ "text": "On",
+ "type": 1,
+ "value": "1"
+ },
+ {
+ "id": 1,
+ "text": "Off",
+ "type": 1,
+ "value": "0"
+ }
+ ]
+ }
+ },
+ "options": {
+ "tooltipOptions": {
+ "mode": "multi"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with no relevant configurations",
+ "id": 8,
+ "fieldConfig": {
+ "defaults": {
+ "unit": "bytes"
+ }
+ },
+ "options": {
+ "legend": {
+ "displayMode": "list"
+ }
+ }
+ },
+ {
+ "type": "stat",
+ "title": "Panel with empty mappings array - should return null",
+ "id": 9,
+ "fieldConfig": {
+ "defaults": {
+ "mappings": []
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "empty-field"
+ },
+ "properties": [
+ {
+ "id": "mappings",
+ "value": []
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/input/v31.labels_to_fields_merge.json b/apps/dashboard/pkg/migration/testdata/input/v31.labels_to_fields_merge.json
new file mode 100644
index 00000000000..be959f93568
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/input/v31.labels_to_fields_merge.json
@@ -0,0 +1,126 @@
+{
+ "title": "V31 LabelsToFields Merge Migration Test Dashboard",
+ "schemaVersion": 30,
+ "panels": [
+ {
+ "type": "timeseries",
+ "title": "Panel with basic labelsToFields transformation",
+ "id": 1,
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with labelsToFields options preserved",
+ "id": 9,
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "mode": "rows",
+ "keepLabels": ["job", "instance", "region"],
+ "valueLabel": "value"
+ }
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with multiple labelsToFields transformations",
+ "id": 2,
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ },
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "calculateField",
+ "options": {}
+ },
+ {
+ "id": "labelsToFields",
+ "options": {
+ "mode": "rows"
+ }
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with no transformations",
+ "id": 3
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with other transformations only",
+ "id": 4,
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ },
+ {
+ "id": "reduce",
+ "options": {}
+ }
+ ]
+ },
+ {
+ "type": "row",
+ "title": "Row with nested panels",
+ "id": 5,
+ "collapsed": false,
+ "panels": [
+ {
+ "type": "timeseries",
+ "title": "Nested panel with labelsToFields",
+ "id": 6,
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Nested panel without labelsToFields",
+ "id": 7,
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "timeseries",
+ "title": "Panel with labelsToFields and existing merge",
+ "id": 8,
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "reduce",
+ "options": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/input/v32.no_op_migration.json b/apps/dashboard/pkg/migration/testdata/input/v32.no_op_migration.json
new file mode 100644
index 00000000000..a190ad11be0
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/input/v32.no_op_migration.json
@@ -0,0 +1,80 @@
+{
+ "title": "V32 No-Op Migration Test Dashboard",
+ "schemaVersion": 31,
+ "panels": [
+ {
+ "type": "timeseries",
+ "title": "Panel with transformations remains unchanged",
+ "id": 1,
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "mode": "rows",
+ "keepLabels": ["job", "instance"]
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ]
+ },
+ {
+ "type": "graph",
+ "title": "Graph panel remains unchanged",
+ "id": 2,
+ "yAxes": [
+ {
+ "show": true,
+ "min": null,
+ "max": null
+ }
+ ]
+ },
+ {
+ "type": "row",
+ "title": "Row with nested panels",
+ "id": 3,
+ "collapsed": false,
+ "panels": [
+ {
+ "type": "stat",
+ "title": "Nested stat panel",
+ "id": 4,
+ "fieldConfig": {
+ "defaults": {
+ "unit": "bytes"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "templating": {
+ "list": [
+ {
+ "name": "environment",
+ "type": "query",
+ "datasource": "prometheus",
+ "options": []
+ }
+ ]
+ },
+ "annotations": {
+ "list": [
+ {
+ "name": "Deployments",
+ "datasource": "grafana",
+ "enable": true
+ }
+ ]
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
+ }
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/output/v29.query_variables_refresh_and_options.json b/apps/dashboard/pkg/migration/testdata/output/v29.query_variables_refresh_and_options.json
new file mode 100644
index 00000000000..102a1ad1ebb
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/output/v29.query_variables_refresh_and_options.json
@@ -0,0 +1,176 @@
+{
+ "panels": [
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "id": 1,
+ "targets": [
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "expr": "up",
+ "refId": "A"
+ }
+ ],
+ "title": "Test Panel",
+ "type": "timeseries"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 41,
+ "templating": {
+ "list": [
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "never_refresh_with_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "never_refresh_without_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "dashboard_refresh_with_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "dashboard_refresh_without_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "timerange_refresh_with_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "timerange_refresh_without_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "no_refresh_with_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "no_refresh_without_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "unknown_refresh_with_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "unknown_refresh_without_options",
+ "options": [],
+ "refresh": 1,
+ "type": "query"
+ },
+ {
+ "name": "custom_variable",
+ "options": [
+ {
+ "text": "custom",
+ "value": "custom"
+ }
+ ],
+ "type": "custom"
+ },
+ {
+ "name": "textbox_variable",
+ "options": [
+ {
+ "text": "Hello",
+ "value": "World"
+ }
+ ],
+ "type": "textbox"
+ },
+ {
+ "name": "datasource_variable",
+ "options": [
+ {
+ "text": "ds",
+ "value": "ds"
+ }
+ ],
+ "type": "datasource"
+ },
+ {
+ "name": "interval_variable",
+ "options": [
+ {
+ "text": "1m",
+ "value": "1m"
+ }
+ ],
+ "type": "interval"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ]
+ },
+ "title": "V29 Query Variables Refresh and Options Migration Test Dashboard"
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/output/v30.value_mappings_and_tooltip_options.json b/apps/dashboard/pkg/migration/testdata/output/v30.value_mappings_and_tooltip_options.json
new file mode 100644
index 00000000000..508e41cb1f6
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/output/v30.value_mappings_and_tooltip_options.json
@@ -0,0 +1,373 @@
+{
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "options": {
+ "0": {
+ "color": "green",
+ "text": "Down"
+ },
+ "1": {
+ "color": "green",
+ "text": "Up"
+ }
+ },
+ "type": "value"
+ },
+ {
+ "options": {
+ "from": 10,
+ "result": {
+ "color": "green",
+ "text": "Medium"
+ },
+ "to": 20
+ },
+ "type": "range"
+ },
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "color": "green",
+ "text": "Null Value"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "test-field"
+ },
+ "properties": [
+ {
+ "id": "mappings",
+ "value": [
+ {
+ "options": {
+ "1": {
+ "text": "Override Up"
+ }
+ },
+ "type": "value"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "id": 1,
+ "options": {
+ "tooltip": {
+ "mode": "multi"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with legacy value mappings and tooltip options",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 2,
+ "options": {
+ "tooltip": {
+ "mode": "single"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "XY Chart with tooltip options only",
+ "type": "xychart"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 3,
+ "options": {
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "XY Chart2 with tooltip options",
+ "type": "xychart2"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 4,
+ "options": {
+ "tooltip": {
+ "mode": "single"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Graph panel gets migrated to timeseries and tooltip",
+ "type": "graph"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "options": {
+ "100": {
+ "text": "Critical"
+ }
+ },
+ "type": "value"
+ },
+ {
+ "options": {
+ "from": 50,
+ "result": {
+ "text": "Warning"
+ },
+ "to": 99
+ },
+ "type": "range"
+ },
+ {
+ "options": {
+ "from": 0,
+ "result": {
+ "text": "OK"
+ },
+ "to": 49
+ },
+ "type": "range"
+ }
+ ]
+ }
+ },
+ "id": 5,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with complex value mappings",
+ "type": "stat"
+ },
+ {
+ "collapsed": true,
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 6,
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "options": {
+ "0": {
+ "text": "Off"
+ },
+ "1": {
+ "text": "On"
+ }
+ },
+ "type": "value"
+ }
+ ]
+ }
+ },
+ "id": 7,
+ "options": {
+ "tooltip": {
+ "mode": "multi"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Nested panel with both migrations",
+ "type": "timeseries"
+ }
+ ],
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Collapsed Row with nested panels",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "unit": "bytes"
+ }
+ },
+ "id": 8,
+ "options": {
+ "legend": {
+ "displayMode": "list",
+ "showLegend": true
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with no relevant configurations",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": []
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "empty-field"
+ },
+ "properties": [
+ {
+ "id": "mappings",
+ "value": []
+ }
+ ]
+ }
+ ]
+ },
+ "id": 9,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with empty mappings array - should return null",
+ "type": "stat"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 41,
+ "title": "V30 Value Mappings and Tooltip Options Migration Test Dashboard"
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/output/v31.labels_to_fields_merge.json b/apps/dashboard/pkg/migration/testdata/output/v31.labels_to_fields_merge.json
new file mode 100644
index 00000000000..d48c4f46c2e
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/output/v31.labels_to_fields_merge.json
@@ -0,0 +1,290 @@
+{
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 1,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with basic labelsToFields transformation",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 9,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with labelsToFields options preserved",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "keepLabels": [
+ "job",
+ "instance",
+ "region"
+ ],
+ "mode": "rows",
+ "valueLabel": "value"
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 2,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with multiple labelsToFields transformations",
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ },
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "calculateField",
+ "options": {}
+ },
+ {
+ "id": "labelsToFields",
+ "options": {
+ "mode": "rows"
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 3,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with no transformations",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 4,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with other transformations only",
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ },
+ {
+ "id": "reduce",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 5,
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 6,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Nested panel with labelsToFields",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 7,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Nested panel without labelsToFields",
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ }
+ ],
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Row with nested panels",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 8,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with labelsToFields and existing merge",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "reduce",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 41,
+ "title": "V31 LabelsToFields Merge Migration Test Dashboard"
+}
\ No newline at end of file
diff --git a/apps/dashboard/pkg/migration/testdata/output/v32.no_op_migration.json b/apps/dashboard/pkg/migration/testdata/output/v32.no_op_migration.json
new file mode 100644
index 00000000000..ad9e5158fe4
--- /dev/null
+++ b/apps/dashboard/pkg/migration/testdata/output/v32.no_op_migration.json
@@ -0,0 +1,159 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "datasource": {
+ "uid": "grafana"
+ },
+ "enable": true,
+ "name": "Deployments"
+ }
+ ]
+ },
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 1,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Panel with transformations remains unchanged",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "keepLabels": [
+ "job",
+ "instance"
+ ],
+ "mode": "rows"
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 2,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Graph panel remains unchanged",
+ "type": "graph",
+ "yAxes": [
+ {
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "id": 3,
+ "panels": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "unit": "bytes"
+ }
+ },
+ "id": 4,
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Nested stat panel",
+ "type": "stat"
+ }
+ ],
+ "targets": [
+ {
+ "datasource": {
+ "apiVersion": "v1",
+ "type": "prometheus",
+ "uid": "default-ds-uid"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Row with nested panels",
+ "type": "row"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 41,
+ "templating": {
+ "list": [
+ {
+ "datasource": {
+ "uid": "prometheus"
+ },
+ "name": "environment",
+ "options": [],
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ]
+ },
+ "title": "V32 No-Op Migration Test Dashboard"
+}
\ No newline at end of file
diff --git a/apps/folder/go.mod b/apps/folder/go.mod
index c12fa59b93d..88db83aa995 100644
--- a/apps/folder/go.mod
+++ b/apps/folder/go.mod
@@ -3,9 +3,9 @@ module github.com/grafana/grafana/apps/folder
go 1.24.4
require (
- github.com/grafana/grafana-app-sdk v0.39.0
+ github.com/grafana/grafana-app-sdk v0.39.2
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
- k8s.io/apimachinery v0.33.1
+ k8s.io/apimachinery v0.33.2
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -23,7 +23,7 @@ require (
github.com/go-test/deep v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
@@ -53,7 +53,7 @@ require (
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/client-go v0.33.1 // indirect
+ k8s.io/client-go v0.33.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
diff --git a/apps/folder/go.sum b/apps/folder/go.sum
index c61276e084f..8f346fcbfcd 100644
--- a/apps/folder/go.sum
+++ b/apps/folder/go.sum
@@ -32,10 +32,10 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grafana/grafana-app-sdk v0.39.0 h1:WC2E9BKXWDX/e2bajdAFjQEyyWf9BFp7Yzbjm6T1T1w=
-github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
-github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
-github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -150,12 +150,12 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
-k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
-k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
-k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
-k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/apps/iam/go.mod b/apps/iam/go.mod
index 811abf007e5..5c4086d8596 100644
--- a/apps/iam/go.mod
+++ b/apps/iam/go.mod
@@ -3,9 +3,9 @@ module github.com/grafana/grafana/apps/iam
go 1.24.4
require (
- github.com/grafana/grafana-app-sdk v0.39.0
+ github.com/grafana/grafana-app-sdk v0.39.2
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
- k8s.io/apimachinery v0.33.1
+ k8s.io/apimachinery v0.33.2
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -23,7 +23,7 @@ require (
github.com/go-test/deep v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
@@ -53,7 +53,7 @@ require (
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/client-go v0.33.1 // indirect
+ k8s.io/client-go v0.33.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
diff --git a/apps/iam/go.sum b/apps/iam/go.sum
index c61276e084f..8f346fcbfcd 100644
--- a/apps/iam/go.sum
+++ b/apps/iam/go.sum
@@ -32,10 +32,10 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grafana/grafana-app-sdk v0.39.0 h1:WC2E9BKXWDX/e2bajdAFjQEyyWf9BFp7Yzbjm6T1T1w=
-github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
-github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
-github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -150,12 +150,12 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
-k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
-k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
-k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
-k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/apps/iam/kinds/manifest.cue b/apps/iam/kinds/manifest.cue
index f2f4b519d7b..032261e9030 100644
--- a/apps/iam/kinds/manifest.cue
+++ b/apps/iam/kinds/manifest.cue
@@ -3,5 +3,16 @@ package kinds
manifest: {
appName: "iam"
groupOverride: "iam.grafana.app"
- kinds: [ globalrole, globalrolebinding, corerole, role, rolebinding, resourcepermission ]
+ kinds: [
+ globalrole,
+ globalrolebinding,
+ corerole,
+ role,
+ rolebinding,
+ resourcepermission,
+ user,
+ team,
+ teambinding,
+ serviceaccount,
+ ]
}
diff --git a/apps/iam/kinds/serviceaccount.cue b/apps/iam/kinds/serviceaccount.cue
new file mode 100644
index 00000000000..22fb1e9e9cf
--- /dev/null
+++ b/apps/iam/kinds/serviceaccount.cue
@@ -0,0 +1,24 @@
+package kinds
+
+import (
+ "github.com/grafana/grafana/apps/iam/kinds/v0alpha1"
+)
+
+serviceaccount: {
+ kind: "ServiceAccount"
+ pluralName: "ServiceAccounts"
+ current: "v0alpha1"
+
+ codegen: {
+ ts: { enabled: false }
+ go: { enabled: true }
+ }
+
+ versions: {
+ "v0alpha1": {
+ schema: {
+ spec: v0alpha1.ServiceAccountSpec
+ }
+ }
+ }
+}
diff --git a/apps/iam/kinds/team.cue b/apps/iam/kinds/team.cue
new file mode 100644
index 00000000000..284d9e601ea
--- /dev/null
+++ b/apps/iam/kinds/team.cue
@@ -0,0 +1,24 @@
+package kinds
+
+import (
+ "github.com/grafana/grafana/apps/iam/kinds/v0alpha1"
+)
+
+team: {
+ kind: "Team"
+ pluralName: "Teams"
+ current: "v0alpha1"
+
+ codegen: {
+ ts: { enabled: false }
+ go: { enabled: true }
+ }
+
+ versions: {
+ "v0alpha1": {
+ schema: {
+ spec: v0alpha1.TeamSpec
+ }
+ }
+ }
+}
diff --git a/apps/iam/kinds/teambinding.cue b/apps/iam/kinds/teambinding.cue
new file mode 100644
index 00000000000..3f0805b0307
--- /dev/null
+++ b/apps/iam/kinds/teambinding.cue
@@ -0,0 +1,24 @@
+package kinds
+
+import (
+ "github.com/grafana/grafana/apps/iam/kinds/v0alpha1"
+)
+
+teambinding: {
+ kind: "TeamBinding"
+ pluralName: "TeamBindings"
+ current: "v0alpha1"
+
+ codegen: {
+ ts: { enabled: false }
+ go: { enabled: true }
+ }
+
+ versions: {
+ "v0alpha1": {
+ schema: {
+ spec: v0alpha1.TeamBindingSpec
+ }
+ }
+ }
+}
diff --git a/apps/iam/kinds/user.cue b/apps/iam/kinds/user.cue
new file mode 100644
index 00000000000..f5e0f04377b
--- /dev/null
+++ b/apps/iam/kinds/user.cue
@@ -0,0 +1,24 @@
+package kinds
+
+import (
+ "github.com/grafana/grafana/apps/iam/kinds/v0alpha1"
+)
+
+user: {
+ kind: "User"
+ pluralName: "Users"
+ current: "v0alpha1"
+
+ codegen: {
+ ts: { enabled: false }
+ go: { enabled: true }
+ }
+
+ versions: {
+ "v0alpha1": {
+ schema: {
+ spec: v0alpha1.UserSpec
+ }
+ }
+ }
+}
diff --git a/apps/iam/kinds/v0alpha1/resourcepermission.cue b/apps/iam/kinds/v0alpha1/resourcepermission.cue
index 4cb02c3c400..5cb8c4de5d0 100644
--- a/apps/iam/kinds/v0alpha1/resourcepermission.cue
+++ b/apps/iam/kinds/v0alpha1/resourcepermission.cue
@@ -21,5 +21,3 @@ ResourcePermission: {
resource: #Resource
permissions: [...#Permission]
}
-
-
diff --git a/apps/iam/kinds/v0alpha1/rolespec.cue b/apps/iam/kinds/v0alpha1/rolespec.cue
index 46d6ce1f2c4..b7934f0174e 100644
--- a/apps/iam/kinds/v0alpha1/rolespec.cue
+++ b/apps/iam/kinds/v0alpha1/rolespec.cue
@@ -10,6 +10,7 @@ RoleSpec: {
// Display name of the role
title: string
+ description: string
version: int
group: string
@@ -20,4 +21,3 @@ RoleSpec: {
// created?
// updated?
}
-
diff --git a/apps/iam/kinds/v0alpha1/serviceaccountspec.cue b/apps/iam/kinds/v0alpha1/serviceaccountspec.cue
new file mode 100644
index 00000000000..9474fc1a06f
--- /dev/null
+++ b/apps/iam/kinds/v0alpha1/serviceaccountspec.cue
@@ -0,0 +1,6 @@
+package v0alpha1
+
+ServiceAccountSpec: {
+ title: string
+ disabled: bool
+}
diff --git a/apps/iam/kinds/v0alpha1/teambindingspec.cue b/apps/iam/kinds/v0alpha1/teambindingspec.cue
new file mode 100644
index 00000000000..3bd130c902d
--- /dev/null
+++ b/apps/iam/kinds/v0alpha1/teambindingspec.cue
@@ -0,0 +1,20 @@
+package v0alpha1
+
+TeamBindingSpec: {
+ #Subject: {
+ // uid of the identity
+ name: string
+ // permission of the identity in the team
+ permission: TeamPermission
+ }
+
+ subjects: [...#Subject]
+ teamRef: TeamRef
+}
+
+TeamRef:{
+ // Name is the unique identifier for a team.
+ name: string
+}
+
+TeamPermission: "admin" | "member"
diff --git a/apps/iam/kinds/v0alpha1/teamspec.cue b/apps/iam/kinds/v0alpha1/teamspec.cue
new file mode 100644
index 00000000000..392c5fedb4a
--- /dev/null
+++ b/apps/iam/kinds/v0alpha1/teamspec.cue
@@ -0,0 +1,6 @@
+package v0alpha1
+
+TeamSpec: {
+ title: string
+ email: string
+}
diff --git a/apps/iam/kinds/v0alpha1/userspec.cue b/apps/iam/kinds/v0alpha1/userspec.cue
new file mode 100644
index 00000000000..8ddcf57151d
--- /dev/null
+++ b/apps/iam/kinds/v0alpha1/userspec.cue
@@ -0,0 +1,13 @@
+package v0alpha1
+
+UserSpec: {
+ disabled: bool
+ email: string
+ emailVerified: bool
+ grafanaAdmin: bool
+ login: string
+ name: string
+ provisioned: bool
+
+ // What to do with salt, rands and password?
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/corerole_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/corerole_spec_gen.go
index eb2c1d52e40..ac0b41e1972 100644
--- a/apps/iam/pkg/apis/iam/v0alpha1/corerole_spec_gen.go
+++ b/apps/iam/pkg/apis/iam/v0alpha1/corerole_spec_gen.go
@@ -18,9 +18,10 @@ func NewCoreRolespecPermission() *CoreRolespecPermission {
// +k8s:openapi-gen=true
type CoreRoleSpec struct {
// Display name of the role
- Title string `json:"title"`
- Version int64 `json:"version"`
- Group string `json:"group"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Version int64 `json:"version"`
+ Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/extensions.go b/apps/iam/pkg/apis/iam/v0alpha1/extensions.go
new file mode 100644
index 00000000000..c0c5a11f7e3
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/extensions.go
@@ -0,0 +1,43 @@
+package v0alpha1
+
+import (
+ "fmt"
+
+ "github.com/grafana/grafana/pkg/apimachinery/utils"
+)
+
+func (u User) AuthID() string {
+ meta, err := utils.MetaAccessor(&u)
+ if err != nil {
+ return ""
+ }
+ // TODO: Workaround until we move all definitions
+ // After having all resource definitions here in the app, we can remove this
+ // and we need to change the List authorization to use the MetaAccessor and the GetDeprecatedInternalID method
+ //nolint:staticcheck
+ return fmt.Sprintf("%d", meta.GetDeprecatedInternalID())
+}
+
+func (s ServiceAccount) AuthID() string {
+ meta, err := utils.MetaAccessor(&s)
+ if err != nil {
+ return ""
+ }
+ // TODO: Workaround until we move all definitions
+ // After having all resource definitions here in the app, we can remove this
+ // and we need to change the List authorization to use the MetaAccessor and the GetDeprecatedInternalID method
+ //nolint:staticcheck
+ return fmt.Sprintf("%d", meta.GetDeprecatedInternalID())
+}
+
+func (t Team) AuthID() string {
+ meta, err := utils.MetaAccessor(&t)
+ if err != nil {
+ return ""
+ }
+ // TODO: Workaround until we move all definitions
+ // After having all resource definitions here in the app, we can remove this
+ // and we need to change the List authorization to use the MetaAccessor and the GetDeprecatedInternalID method
+ //nolint:staticcheck
+ return fmt.Sprintf("%d", meta.GetDeprecatedInternalID())
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/globalrole_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/globalrole_spec_gen.go
index 785d2d5724b..1ce8d65646f 100644
--- a/apps/iam/pkg/apis/iam/v0alpha1/globalrole_spec_gen.go
+++ b/apps/iam/pkg/apis/iam/v0alpha1/globalrole_spec_gen.go
@@ -18,9 +18,10 @@ func NewGlobalRolespecPermission() *GlobalRolespecPermission {
// +k8s:openapi-gen=true
type GlobalRoleSpec struct {
// Display name of the role
- Title string `json:"title"`
- Version int64 `json:"version"`
- Group string `json:"group"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Version int64 `json:"version"`
+ Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/role_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/role_spec_gen.go
index f1a165dba4e..5a8185cd25c 100644
--- a/apps/iam/pkg/apis/iam/v0alpha1/role_spec_gen.go
+++ b/apps/iam/pkg/apis/iam/v0alpha1/role_spec_gen.go
@@ -18,9 +18,10 @@ func NewRolespecPermission() *RolespecPermission {
// +k8s:openapi-gen=true
type RoleSpec struct {
// Display name of the role
- Title string `json:"title"`
- Version int64 `json:"version"`
- Group string `json:"group"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Version int64 `json:"version"`
+ Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_codec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_codec_gen.go
new file mode 100644
index 00000000000..0f5b3e7783a
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// ServiceAccountJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type ServiceAccountJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*ServiceAccountJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*ServiceAccountJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &ServiceAccountJSONCodec{}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_metadata_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_metadata_gen.go
new file mode 100644
index 00000000000..3a846141f87
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type ServiceAccountMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewServiceAccountMetadata creates a new ServiceAccountMetadata object.
+func NewServiceAccountMetadata() *ServiceAccountMetadata {
+ return &ServiceAccountMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_object_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_object_gen.go
new file mode 100644
index 00000000000..081e244dd6e
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type ServiceAccount struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the ServiceAccount
+ Spec ServiceAccountSpec `json:"spec" yaml:"spec"`
+
+ Status ServiceAccountStatus `json:"status" yaml:"status"`
+}
+
+func (o *ServiceAccount) GetSpec() any {
+ return o.Spec
+}
+
+func (o *ServiceAccount) SetSpec(spec any) error {
+ cast, ok := spec.(ServiceAccountSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *ServiceAccount) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *ServiceAccount) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *ServiceAccount) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(ServiceAccountStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type ServiceAccountStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *ServiceAccount) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *ServiceAccount) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *ServiceAccount) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *ServiceAccount) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *ServiceAccount) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *ServiceAccount) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *ServiceAccount) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *ServiceAccount) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *ServiceAccount) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *ServiceAccount) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *ServiceAccount) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *ServiceAccount) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *ServiceAccount) DeepCopy() *ServiceAccount {
+ cpy := &ServiceAccount{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *ServiceAccount) DeepCopyInto(dst *ServiceAccount) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &ServiceAccount{}
+
+// +k8s:openapi-gen=true
+type ServiceAccountList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []ServiceAccount `json:"items" yaml:"items"`
+}
+
+func (o *ServiceAccountList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *ServiceAccountList) Copy() resource.ListObject {
+ cpy := &ServiceAccountList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]ServiceAccount, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*ServiceAccount); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *ServiceAccountList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *ServiceAccountList) SetItems(items []resource.Object) {
+ o.Items = make([]ServiceAccount, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*ServiceAccount)
+ }
+}
+
+func (o *ServiceAccountList) DeepCopy() *ServiceAccountList {
+ cpy := &ServiceAccountList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *ServiceAccountList) DeepCopyInto(dst *ServiceAccountList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &ServiceAccountList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *ServiceAccountSpec) DeepCopy() *ServiceAccountSpec {
+ cpy := &ServiceAccountSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *ServiceAccountSpec) DeepCopyInto(dst *ServiceAccountSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of ServiceAccountStatus
+func (s *ServiceAccountStatus) DeepCopy() *ServiceAccountStatus {
+ cpy := &ServiceAccountStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies ServiceAccountStatus into another ServiceAccountStatus object
+func (s *ServiceAccountStatus) DeepCopyInto(dst *ServiceAccountStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_schema_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_schema_gen.go
new file mode 100644
index 00000000000..ea48c864739
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaServiceAccount = resource.NewSimpleSchema("iam.grafana.app", "v0alpha1", &ServiceAccount{}, &ServiceAccountList{}, resource.WithKind("ServiceAccount"),
+ resource.WithPlural("serviceaccounts"), resource.WithScope(resource.NamespacedScope))
+ kindServiceAccount = resource.Kind{
+ Schema: schemaServiceAccount,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &ServiceAccountJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func ServiceAccountKind() resource.Kind {
+ return kindServiceAccount
+}
+
+// Schema returns a resource.SimpleSchema representation of ServiceAccount
+func ServiceAccountSchema() *resource.SimpleSchema {
+ return schemaServiceAccount
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindServiceAccount
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_spec_gen.go
new file mode 100644
index 00000000000..a6bfffd53f9
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_spec_gen.go
@@ -0,0 +1,14 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type ServiceAccountSpec struct {
+ Title string `json:"title"`
+ Disabled bool `json:"disabled"`
+}
+
+// NewServiceAccountSpec creates a new ServiceAccountSpec object.
+func NewServiceAccountSpec() *ServiceAccountSpec {
+ return &ServiceAccountSpec{}
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_status_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_status_gen.go
new file mode 100644
index 00000000000..8174df97c23
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/serviceaccount_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type ServiceAccountstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State ServiceAccountStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewServiceAccountstatusOperatorState creates a new ServiceAccountstatusOperatorState object.
+func NewServiceAccountstatusOperatorState() *ServiceAccountstatusOperatorState {
+ return &ServiceAccountstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type ServiceAccountStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]ServiceAccountstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewServiceAccountStatus creates a new ServiceAccountStatus object.
+func NewServiceAccountStatus() *ServiceAccountStatus {
+ return &ServiceAccountStatus{}
+}
+
+// +k8s:openapi-gen=true
+type ServiceAccountStatusOperatorStateState string
+
+const (
+ ServiceAccountStatusOperatorStateStateSuccess ServiceAccountStatusOperatorStateState = "success"
+ ServiceAccountStatusOperatorStateStateInProgress ServiceAccountStatusOperatorStateState = "in_progress"
+ ServiceAccountStatusOperatorStateStateFailed ServiceAccountStatusOperatorStateState = "failed"
+)
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_codec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_codec_gen.go
new file mode 100644
index 00000000000..fb0ede4ef1e
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// TeamJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type TeamJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*TeamJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*TeamJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &TeamJSONCodec{}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_metadata_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_metadata_gen.go
new file mode 100644
index 00000000000..5e833327309
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type TeamMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewTeamMetadata creates a new TeamMetadata object.
+func NewTeamMetadata() *TeamMetadata {
+ return &TeamMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_object_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_object_gen.go
new file mode 100644
index 00000000000..bfc949acfd1
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type Team struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the Team
+ Spec TeamSpec `json:"spec" yaml:"spec"`
+
+ Status TeamStatus `json:"status" yaml:"status"`
+}
+
+func (o *Team) GetSpec() any {
+ return o.Spec
+}
+
+func (o *Team) SetSpec(spec any) error {
+ cast, ok := spec.(TeamSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *Team) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *Team) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *Team) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(TeamStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type TeamStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *Team) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *Team) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *Team) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *Team) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *Team) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *Team) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *Team) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *Team) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *Team) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *Team) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *Team) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *Team) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *Team) DeepCopy() *Team {
+ cpy := &Team{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *Team) DeepCopyInto(dst *Team) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &Team{}
+
+// +k8s:openapi-gen=true
+type TeamList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []Team `json:"items" yaml:"items"`
+}
+
+func (o *TeamList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *TeamList) Copy() resource.ListObject {
+ cpy := &TeamList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]Team, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*Team); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *TeamList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *TeamList) SetItems(items []resource.Object) {
+ o.Items = make([]Team, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*Team)
+ }
+}
+
+func (o *TeamList) DeepCopy() *TeamList {
+ cpy := &TeamList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *TeamList) DeepCopyInto(dst *TeamList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &TeamList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *TeamSpec) DeepCopy() *TeamSpec {
+ cpy := &TeamSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *TeamSpec) DeepCopyInto(dst *TeamSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of TeamStatus
+func (s *TeamStatus) DeepCopy() *TeamStatus {
+ cpy := &TeamStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies TeamStatus into another TeamStatus object
+func (s *TeamStatus) DeepCopyInto(dst *TeamStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_schema_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_schema_gen.go
new file mode 100644
index 00000000000..7a4875cf2d5
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaTeam = resource.NewSimpleSchema("iam.grafana.app", "v0alpha1", &Team{}, &TeamList{}, resource.WithKind("Team"),
+ resource.WithPlural("teams"), resource.WithScope(resource.NamespacedScope))
+ kindTeam = resource.Kind{
+ Schema: schemaTeam,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &TeamJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func TeamKind() resource.Kind {
+ return kindTeam
+}
+
+// Schema returns a resource.SimpleSchema representation of Team
+func TeamSchema() *resource.SimpleSchema {
+ return schemaTeam
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindTeam
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_spec_gen.go
new file mode 100644
index 00000000000..994bfdd59c5
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_spec_gen.go
@@ -0,0 +1,14 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type TeamSpec struct {
+ Title string `json:"title"`
+ Email string `json:"email"`
+}
+
+// NewTeamSpec creates a new TeamSpec object.
+func NewTeamSpec() *TeamSpec {
+ return &TeamSpec{}
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_status_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/team_status_gen.go
new file mode 100644
index 00000000000..0690e938633
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/team_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type TeamstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State TeamStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewTeamstatusOperatorState creates a new TeamstatusOperatorState object.
+func NewTeamstatusOperatorState() *TeamstatusOperatorState {
+ return &TeamstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type TeamStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]TeamstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewTeamStatus creates a new TeamStatus object.
+func NewTeamStatus() *TeamStatus {
+ return &TeamStatus{}
+}
+
+// +k8s:openapi-gen=true
+type TeamStatusOperatorStateState string
+
+const (
+ TeamStatusOperatorStateStateSuccess TeamStatusOperatorStateState = "success"
+ TeamStatusOperatorStateStateInProgress TeamStatusOperatorStateState = "in_progress"
+ TeamStatusOperatorStateStateFailed TeamStatusOperatorStateState = "failed"
+)
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_codec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_codec_gen.go
new file mode 100644
index 00000000000..358f530ca7b
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// TeamBindingJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type TeamBindingJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*TeamBindingJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*TeamBindingJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &TeamBindingJSONCodec{}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_metadata_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_metadata_gen.go
new file mode 100644
index 00000000000..b1e7ab5f8ab
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type TeamBindingMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewTeamBindingMetadata creates a new TeamBindingMetadata object.
+func NewTeamBindingMetadata() *TeamBindingMetadata {
+ return &TeamBindingMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_object_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_object_gen.go
new file mode 100644
index 00000000000..6c9f6f407e3
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type TeamBinding struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the TeamBinding
+ Spec TeamBindingSpec `json:"spec" yaml:"spec"`
+
+ Status TeamBindingStatus `json:"status" yaml:"status"`
+}
+
+func (o *TeamBinding) GetSpec() any {
+ return o.Spec
+}
+
+func (o *TeamBinding) SetSpec(spec any) error {
+ cast, ok := spec.(TeamBindingSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *TeamBinding) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *TeamBinding) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *TeamBinding) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(TeamBindingStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type TeamBindingStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *TeamBinding) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *TeamBinding) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *TeamBinding) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *TeamBinding) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *TeamBinding) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *TeamBinding) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *TeamBinding) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *TeamBinding) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *TeamBinding) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *TeamBinding) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *TeamBinding) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *TeamBinding) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *TeamBinding) DeepCopy() *TeamBinding {
+ cpy := &TeamBinding{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *TeamBinding) DeepCopyInto(dst *TeamBinding) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &TeamBinding{}
+
+// +k8s:openapi-gen=true
+type TeamBindingList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []TeamBinding `json:"items" yaml:"items"`
+}
+
+func (o *TeamBindingList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *TeamBindingList) Copy() resource.ListObject {
+ cpy := &TeamBindingList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]TeamBinding, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*TeamBinding); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *TeamBindingList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *TeamBindingList) SetItems(items []resource.Object) {
+ o.Items = make([]TeamBinding, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*TeamBinding)
+ }
+}
+
+func (o *TeamBindingList) DeepCopy() *TeamBindingList {
+ cpy := &TeamBindingList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *TeamBindingList) DeepCopyInto(dst *TeamBindingList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &TeamBindingList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *TeamBindingSpec) DeepCopy() *TeamBindingSpec {
+ cpy := &TeamBindingSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *TeamBindingSpec) DeepCopyInto(dst *TeamBindingSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of TeamBindingStatus
+func (s *TeamBindingStatus) DeepCopy() *TeamBindingStatus {
+ cpy := &TeamBindingStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies TeamBindingStatus into another TeamBindingStatus object
+func (s *TeamBindingStatus) DeepCopyInto(dst *TeamBindingStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go
new file mode 100644
index 00000000000..e3c2c11a8b5
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaTeamBinding = resource.NewSimpleSchema("iam.grafana.app", "v0alpha1", &TeamBinding{}, &TeamBindingList{}, resource.WithKind("TeamBinding"),
+ resource.WithPlural("teambindings"), resource.WithScope(resource.NamespacedScope))
+ kindTeamBinding = resource.Kind{
+ Schema: schemaTeamBinding,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &TeamBindingJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func TeamBindingKind() resource.Kind {
+ return kindTeamBinding
+}
+
+// Schema returns a resource.SimpleSchema representation of TeamBinding
+func TeamBindingSchema() *resource.SimpleSchema {
+ return schemaTeamBinding
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindTeamBinding
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go
new file mode 100644
index 00000000000..0e58323533e
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_spec_gen.go
@@ -0,0 +1,49 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type TeamBindingspecSubject struct {
+ // uid of the identity
+ Name string `json:"name"`
+ // permission of the identity in the team
+ Permission TeamBindingTeamPermission `json:"permission"`
+}
+
+// NewTeamBindingspecSubject creates a new TeamBindingspecSubject object.
+func NewTeamBindingspecSubject() *TeamBindingspecSubject {
+ return &TeamBindingspecSubject{}
+}
+
+// +k8s:openapi-gen=true
+type TeamBindingTeamPermission string
+
+const (
+ TeamBindingTeamPermissionAdmin TeamBindingTeamPermission = "admin"
+ TeamBindingTeamPermissionMember TeamBindingTeamPermission = "member"
+)
+
+// +k8s:openapi-gen=true
+type TeamBindingTeamRef struct {
+ // Name is the unique identifier for a team.
+ Name string `json:"name"`
+}
+
+// NewTeamBindingTeamRef creates a new TeamBindingTeamRef object.
+func NewTeamBindingTeamRef() *TeamBindingTeamRef {
+ return &TeamBindingTeamRef{}
+}
+
+// +k8s:openapi-gen=true
+type TeamBindingSpec struct {
+ Subjects []TeamBindingspecSubject `json:"subjects"`
+ TeamRef TeamBindingTeamRef `json:"teamRef"`
+}
+
+// NewTeamBindingSpec creates a new TeamBindingSpec object.
+func NewTeamBindingSpec() *TeamBindingSpec {
+ return &TeamBindingSpec{
+ Subjects: []TeamBindingspecSubject{},
+ TeamRef: *NewTeamBindingTeamRef(),
+ }
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/teambinding_status_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_status_gen.go
new file mode 100644
index 00000000000..221eb320ae7
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/teambinding_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type TeamBindingstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State TeamBindingStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewTeamBindingstatusOperatorState creates a new TeamBindingstatusOperatorState object.
+func NewTeamBindingstatusOperatorState() *TeamBindingstatusOperatorState {
+ return &TeamBindingstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type TeamBindingStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]TeamBindingstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewTeamBindingStatus creates a new TeamBindingStatus object.
+func NewTeamBindingStatus() *TeamBindingStatus {
+ return &TeamBindingStatus{}
+}
+
+// +k8s:openapi-gen=true
+type TeamBindingStatusOperatorStateState string
+
+const (
+ TeamBindingStatusOperatorStateStateSuccess TeamBindingStatusOperatorStateState = "success"
+ TeamBindingStatusOperatorStateStateInProgress TeamBindingStatusOperatorStateState = "in_progress"
+ TeamBindingStatusOperatorStateStateFailed TeamBindingStatusOperatorStateState = "failed"
+)
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_codec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_codec_gen.go
new file mode 100644
index 00000000000..b37a806a30d
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// UserJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type UserJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*UserJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*UserJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &UserJSONCodec{}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_metadata_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_metadata_gen.go
new file mode 100644
index 00000000000..8b1e19a94ab
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type UserMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewUserMetadata creates a new UserMetadata object.
+func NewUserMetadata() *UserMetadata {
+ return &UserMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_object_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_object_gen.go
new file mode 100644
index 00000000000..ce2defa33a8
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type User struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the User
+ Spec UserSpec `json:"spec" yaml:"spec"`
+
+ Status UserStatus `json:"status" yaml:"status"`
+}
+
+func (o *User) GetSpec() any {
+ return o.Spec
+}
+
+func (o *User) SetSpec(spec any) error {
+ cast, ok := spec.(UserSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *User) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *User) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *User) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(UserStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type UserStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *User) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *User) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *User) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *User) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *User) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *User) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *User) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *User) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *User) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *User) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *User) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *User) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *User) DeepCopy() *User {
+ cpy := &User{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *User) DeepCopyInto(dst *User) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &User{}
+
+// +k8s:openapi-gen=true
+type UserList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []User `json:"items" yaml:"items"`
+}
+
+func (o *UserList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *UserList) Copy() resource.ListObject {
+ cpy := &UserList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]User, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*User); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *UserList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *UserList) SetItems(items []resource.Object) {
+ o.Items = make([]User, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*User)
+ }
+}
+
+func (o *UserList) DeepCopy() *UserList {
+ cpy := &UserList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *UserList) DeepCopyInto(dst *UserList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &UserList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *UserSpec) DeepCopy() *UserSpec {
+ cpy := &UserSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *UserSpec) DeepCopyInto(dst *UserSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of UserStatus
+func (s *UserStatus) DeepCopy() *UserStatus {
+ cpy := &UserStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies UserStatus into another UserStatus object
+func (s *UserStatus) DeepCopyInto(dst *UserStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_schema_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_schema_gen.go
new file mode 100644
index 00000000000..a44d9dfcf2d
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaUser = resource.NewSimpleSchema("iam.grafana.app", "v0alpha1", &User{}, &UserList{}, resource.WithKind("User"),
+ resource.WithPlural("users"), resource.WithScope(resource.NamespacedScope))
+ kindUser = resource.Kind{
+ Schema: schemaUser,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &UserJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func UserKind() resource.Kind {
+ return kindUser
+}
+
+// Schema returns a resource.SimpleSchema representation of User
+func UserSchema() *resource.SimpleSchema {
+ return schemaUser
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindUser
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_spec_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_spec_gen.go
new file mode 100644
index 00000000000..8e83f1d8b5d
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_spec_gen.go
@@ -0,0 +1,20 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type UserSpec struct {
+ Disabled bool `json:"disabled"`
+ Email string `json:"email"`
+ EmailVerified bool `json:"emailVerified"`
+ GrafanaAdmin bool `json:"grafanaAdmin"`
+ Login string `json:"login"`
+ Name string `json:"name"`
+ // What to do with salt, rands and password?
+ Provisioned bool `json:"provisioned"`
+}
+
+// NewUserSpec creates a new UserSpec object.
+func NewUserSpec() *UserSpec {
+ return &UserSpec{}
+}
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/user_status_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/user_status_gen.go
new file mode 100644
index 00000000000..34a138f59ce
--- /dev/null
+++ b/apps/iam/pkg/apis/iam/v0alpha1/user_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type UserstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State UserStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewUserstatusOperatorState creates a new UserstatusOperatorState object.
+func NewUserstatusOperatorState() *UserstatusOperatorState {
+ return &UserstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type UserStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]UserstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewUserStatus creates a new UserStatus object.
+func NewUserStatus() *UserStatus {
+ return &UserStatus{}
+}
+
+// +k8s:openapi-gen=true
+type UserStatusOperatorStateState string
+
+const (
+ UserStatusOperatorStateStateSuccess UserStatusOperatorStateState = "success"
+ UserStatusOperatorStateStateInProgress UserStatusOperatorStateState = "in_progress"
+ UserStatusOperatorStateStateFailed UserStatusOperatorStateState = "failed"
+)
diff --git a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go
index df62f68072a..7a0703d53e3 100644
--- a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go
+++ b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go
@@ -51,6 +51,28 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RoleStatus": schema_pkg_apis_iam_v0alpha1_RoleStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolespecPermission": schema_pkg_apis_iam_v0alpha1_RolespecPermission(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.RolestatusOperatorState": schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccount": schema_pkg_apis_iam_v0alpha1_ServiceAccount(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountList": schema_pkg_apis_iam_v0alpha1_ServiceAccountList(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountSpec": schema_pkg_apis_iam_v0alpha1_ServiceAccountSpec(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountStatus": schema_pkg_apis_iam_v0alpha1_ServiceAccountStatus(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountstatusOperatorState": schema_pkg_apis_iam_v0alpha1_ServiceAccountstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Team": schema_pkg_apis_iam_v0alpha1_Team(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBinding": schema_pkg_apis_iam_v0alpha1_TeamBinding(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingList": schema_pkg_apis_iam_v0alpha1_TeamBindingList(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec": schema_pkg_apis_iam_v0alpha1_TeamBindingSpec(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingStatus": schema_pkg_apis_iam_v0alpha1_TeamBindingStatus(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingTeamRef": schema_pkg_apis_iam_v0alpha1_TeamBindingTeamRef(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject": schema_pkg_apis_iam_v0alpha1_TeamBindingspecSubject(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamBindingstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamList": schema_pkg_apis_iam_v0alpha1_TeamList(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamSpec": schema_pkg_apis_iam_v0alpha1_TeamSpec(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamStatus": schema_pkg_apis_iam_v0alpha1_TeamStatus(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamstatusOperatorState": schema_pkg_apis_iam_v0alpha1_TeamstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.User": schema_pkg_apis_iam_v0alpha1_User(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserList": schema_pkg_apis_iam_v0alpha1_UserList(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserSpec": schema_pkg_apis_iam_v0alpha1_UserSpec(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus": schema_pkg_apis_iam_v0alpha1_UserStatus(ref),
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState": schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref),
}
}
@@ -164,6 +186,13 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
Format: "",
},
},
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -193,7 +222,7 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
},
},
},
- Required: []string{"title", "version", "group", "permissions"},
+ Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -718,6 +747,13 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
Format: "",
},
},
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -747,7 +783,7 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
},
},
},
- Required: []string{"title", "version", "group", "permissions"},
+ Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -1578,6 +1614,13 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
Format: "",
},
},
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -1607,7 +1650,7 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
},
},
},
- Required: []string{"title", "version", "group", "permissions"},
+ Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -1738,3 +1781,968 @@ func schema_pkg_apis_iam_v0alpha1_RolestatusOperatorState(ref common.ReferenceCa
},
}
}
+
+func schema_pkg_apis_iam_v0alpha1_ServiceAccount(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the ServiceAccount",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountSpec", "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_ServiceAccountList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccount"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccount", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_ServiceAccountSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "disabled": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"title", "disabled"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_ServiceAccountStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ServiceAccountstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_ServiceAccountstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_Team(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the Team",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamSpec", "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBinding(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the TeamBinding",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec", "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBinding"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBinding", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "subjects": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject"),
+ },
+ },
+ },
+ },
+ },
+ "teamRef": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingTeamRef"),
+ },
+ },
+ },
+ Required: []string{"subjects", "teamRef"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingTeamRef", "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingTeamRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Name is the unique identifier for a team.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingspecSubject(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Description: "uid of the identity",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "permission": {
+ SchemaProps: spec.SchemaProps{
+ Description: "permission of the identity in the team",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"name", "permission"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamBindingstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Team"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.Team", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "email": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"title", "email"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_TeamstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_User(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the User",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserSpec", "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_UserList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.User"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.User", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_UserSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "disabled": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "email": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "emailVerified": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "grafanaAdmin": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "login": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "provisioned": {
+ SchemaProps: spec.SchemaProps{
+ Description: "What to do with salt, rands and password?",
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"disabled", "email", "emailVerified", "grafanaAdmin", "login", "name", "provisioned"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_UserStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
diff --git a/apps/iam/pkg/apis/iam_manifest.go b/apps/iam/pkg/apis/iam_manifest.go
index b80f5e5eee3..667b7a10354 100644
--- a/apps/iam/pkg/apis/iam_manifest.go
+++ b/apps/iam/pkg/apis/iam_manifest.go
@@ -83,6 +83,50 @@ var appManifestData = app.ManifestData{
},
},
},
+
+ {
+ Kind: "User",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ },
+ },
+ },
+
+ {
+ Kind: "Team",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ },
+ },
+ },
+
+ {
+ Kind: "TeamBinding",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ },
+ },
+ },
+
+ {
+ Kind: "ServiceAccount",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ },
+ },
+ },
},
}
@@ -101,6 +145,10 @@ var kindVersionToGoType = map[string]resource.Kind{
"Role/v0alpha1": v0alpha1.RoleKind(),
"RoleBinding/v0alpha1": v0alpha1.RoleBindingKind(),
"ResourcePermission/v0alpha1": v0alpha1.ResourcePermissionKind(),
+ "User/v0alpha1": v0alpha1.UserKind(),
+ "Team/v0alpha1": v0alpha1.TeamKind(),
+ "TeamBinding/v0alpha1": v0alpha1.TeamBindingKind(),
+ "ServiceAccount/v0alpha1": v0alpha1.ServiceAccountKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
diff --git a/apps/playlist/go.mod b/apps/playlist/go.mod
index 618ea42c9a9..47c762b5a24 100644
--- a/apps/playlist/go.mod
+++ b/apps/playlist/go.mod
@@ -3,9 +3,9 @@ module github.com/grafana/grafana/apps/playlist
go 1.24.4
require (
- github.com/grafana/grafana-app-sdk v0.39.0
- k8s.io/apimachinery v0.33.1
- k8s.io/client-go v0.33.1
+ github.com/grafana/grafana-app-sdk v0.39.2
+ k8s.io/apimachinery v0.33.2
+ k8s.io/client-go v0.33.2
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
)
@@ -31,7 +31,7 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -73,14 +73,14 @@ require (
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.11.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.33.1 // indirect
- k8s.io/apiextensions-apiserver v0.33.1 // indirect
+ k8s.io/api v0.33.2 // indirect
+ k8s.io/apiextensions-apiserver v0.33.2 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
diff --git a/apps/playlist/go.sum b/apps/playlist/go.sum
index 8726cf84afc..9cbf8457905 100644
--- a/apps/playlist/go.sum
+++ b/apps/playlist/go.sum
@@ -47,10 +47,10 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grafana/grafana-app-sdk v0.39.0 h1:WC2E9BKXWDX/e2bajdAFjQEyyWf9BFp7Yzbjm6T1T1w=
-github.com/grafana/grafana-app-sdk v0.39.0/go.mod h1:xRyBQOttgWTc3tGe9pI0upnpEPVhzALf7Mh/61O4zyY=
-github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
-github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -189,10 +189,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
-google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
@@ -206,14 +206,14 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
-k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
-k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
-k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
-k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
-k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
-k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8=
+k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/apps/secret/Makefile b/apps/secret/Makefile
new file mode 100644
index 00000000000..d829f94e596
--- /dev/null
+++ b/apps/secret/Makefile
@@ -0,0 +1,29 @@
+APP_SDK_VERSION := v0.39.2
+APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
+APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk
+
+.PHONY: install-app-sdk
+install-app-sdk: $(APP_SDK_BIN) ## Install the Grafana App SDK
+
+$(APP_SDK_BIN):
+ @echo "Installing Grafana App SDK version $(APP_SDK_VERSION)"
+ @mkdir -p $(APP_SDK_DIR)
+ # The only way to install specific versions of binaries using `go install`
+ # is by setting GOBIN to the directory you want to install the binary to.
+ GOBIN=$(APP_SDK_DIR) go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@$(APP_SDK_VERSION)
+ @touch $@
+
+.PHONY: update-app-sdk
+update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
+ go get github.com/grafana/grafana-app-sdk@$(APP_SDK_VERSION)
+ go mod tidy
+
+.PHONY: generate
+generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generation
+ @$(APP_SDK_BIN) generate \
+ --source=./kinds/ \
+ --gogenpath=./pkg/apis \
+ --grouping=group \
+ --defencoding=none \
+ --noschemasinmanifest \
+ --postprocess
\ No newline at end of file
diff --git a/pkg/apis/secret/v0alpha1/decrypt/buf.gen.yaml b/apps/secret/decrypt/v1beta1/buf.gen.yaml
similarity index 68%
rename from pkg/apis/secret/v0alpha1/decrypt/buf.gen.yaml
rename to apps/secret/decrypt/v1beta1/buf.gen.yaml
index f725fb6452d..b2691bae669 100644
--- a/pkg/apis/secret/v0alpha1/decrypt/buf.gen.yaml
+++ b/apps/secret/decrypt/v1beta1/buf.gen.yaml
@@ -2,11 +2,11 @@ version: v1
plugins:
- plugin: go
- out: pkg/apis/secret/v0alpha1/decrypt
+ out: apps/secret/decrypt/v1beta1
opt:
- paths=source_relative
- plugin: go-grpc
- out: pkg/apis/secret/v0alpha1/decrypt
+ out: apps/secret/decrypt/v1beta1
opt:
- paths=source_relative
- require_unimplemented_servers=false
diff --git a/pkg/apis/secret/v0alpha1/decrypt/buf.yaml b/apps/secret/decrypt/v1beta1/buf.yaml
similarity index 100%
rename from pkg/apis/secret/v0alpha1/decrypt/buf.yaml
rename to apps/secret/decrypt/v1beta1/buf.yaml
diff --git a/pkg/apis/secret/v0alpha1/decrypt/decrypt.pb.go b/apps/secret/decrypt/v1beta1/decrypt.pb.go
similarity index 60%
rename from pkg/apis/secret/v0alpha1/decrypt/decrypt.pb.go
rename to apps/secret/decrypt/v1beta1/decrypt.pb.go
index cffa2065ef0..4e334ff7ca3 100644
--- a/pkg/apis/secret/v0alpha1/decrypt/decrypt.pb.go
+++ b/apps/secret/decrypt/v1beta1/decrypt.pb.go
@@ -4,7 +4,7 @@
// protoc (unknown)
// source: decrypt.proto
-package decrypt
+package decryptv1beta1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -208,45 +208,47 @@ var File_decrypt_proto protoreflect.FileDescriptor
var file_decrypt_proto_rawDesc = string([]byte{
0x0a, 0x0d, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x07, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x22, 0x4f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75,
- 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xea, 0x01, 0x0a, 0x24, 0x53, 0x65,
- 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x6d, 0x0a, 0x10, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x64,
- 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x63, 0x72,
- 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
- 0x52, 0x0f, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x1a, 0x53, 0x0a, 0x14, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x65, 0x63,
- 0x72, 0x79, 0x70, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x51, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
- 0x12, 0x16, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48,
- 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
- 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42,
- 0x08, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x80, 0x01, 0x0a, 0x14, 0x53, 0x65,
- 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
- 0x65, 0x72, 0x12, 0x68, 0x0a, 0x13, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x53, 0x65, 0x63,
- 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x64, 0x65, 0x63, 0x72,
- 0x79, 0x70, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44,
- 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e,
- 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x3d, 0x5a, 0x3b,
- 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61,
- 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61,
- 0x70, 0x69, 0x73, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x2f, 0x76, 0x30, 0x61, 0x6c, 0x70,
- 0x68, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x33,
+ 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x22,
+ 0x4f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65,
+ 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
+ 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61,
+ 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73,
+ 0x22, 0xf8, 0x01, 0x0a, 0x24, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43,
+ 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x74, 0x0a, 0x10, 0x64, 0x65, 0x63,
+ 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x76, 0x31, 0x62,
+ 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43,
+ 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f,
+ 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a,
+ 0x5a, 0x0a, 0x14, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x64, 0x65, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x51, 0x0a, 0x06, 0x52,
+ 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a,
+ 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x8e,
+ 0x01, 0x0a, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65,
+ 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x72, 0x12, 0x76, 0x0a, 0x13, 0x44, 0x65, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x29,
+ 0x2e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e,
+ 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x64, 0x65, 0x63, 0x72,
+ 0x79, 0x70, 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42,
+ 0x47, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72,
+ 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x61, 0x70,
+ 0x70, 0x73, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var (
@@ -263,16 +265,16 @@ func file_decrypt_proto_rawDescGZIP() []byte {
var file_decrypt_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_decrypt_proto_goTypes = []any{
- (*SecureValueDecryptRequest)(nil), // 0: decrypt.SecureValueDecryptRequest
- (*SecureValueDecryptResponseCollection)(nil), // 1: decrypt.SecureValueDecryptResponseCollection
- (*Result)(nil), // 2: decrypt.Result
- nil, // 3: decrypt.SecureValueDecryptResponseCollection.DecryptedValuesEntry
+ (*SecureValueDecryptRequest)(nil), // 0: decryptv1beta1.SecureValueDecryptRequest
+ (*SecureValueDecryptResponseCollection)(nil), // 1: decryptv1beta1.SecureValueDecryptResponseCollection
+ (*Result)(nil), // 2: decryptv1beta1.Result
+ nil, // 3: decryptv1beta1.SecureValueDecryptResponseCollection.DecryptedValuesEntry
}
var file_decrypt_proto_depIdxs = []int32{
- 3, // 0: decrypt.SecureValueDecryptResponseCollection.decrypted_values:type_name -> decrypt.SecureValueDecryptResponseCollection.DecryptedValuesEntry
- 2, // 1: decrypt.SecureValueDecryptResponseCollection.DecryptedValuesEntry.value:type_name -> decrypt.Result
- 0, // 2: decrypt.SecureValueDecrypter.DecryptSecureValues:input_type -> decrypt.SecureValueDecryptRequest
- 1, // 3: decrypt.SecureValueDecrypter.DecryptSecureValues:output_type -> decrypt.SecureValueDecryptResponseCollection
+ 3, // 0: decryptv1beta1.SecureValueDecryptResponseCollection.decrypted_values:type_name -> decryptv1beta1.SecureValueDecryptResponseCollection.DecryptedValuesEntry
+ 2, // 1: decryptv1beta1.SecureValueDecryptResponseCollection.DecryptedValuesEntry.value:type_name -> decryptv1beta1.Result
+ 0, // 2: decryptv1beta1.SecureValueDecrypter.DecryptSecureValues:input_type -> decryptv1beta1.SecureValueDecryptRequest
+ 1, // 3: decryptv1beta1.SecureValueDecrypter.DecryptSecureValues:output_type -> decryptv1beta1.SecureValueDecryptResponseCollection
3, // [3:4] is the sub-list for method output_type
2, // [2:3] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
diff --git a/pkg/apis/secret/v0alpha1/decrypt/decrypt.proto b/apps/secret/decrypt/v1beta1/decrypt.proto
similarity index 88%
rename from pkg/apis/secret/v0alpha1/decrypt/decrypt.proto
rename to apps/secret/decrypt/v1beta1/decrypt.proto
index bf328ff5217..a8ee64de420 100644
--- a/pkg/apis/secret/v0alpha1/decrypt/decrypt.proto
+++ b/apps/secret/decrypt/v1beta1/decrypt.proto
@@ -1,8 +1,8 @@
syntax = "proto3";
-package decrypt;
+package decryptv1beta1;
-option go_package = "github.com/grafana/grafana/pkg/apis/secret/v0alpha1/decrypt";
+option go_package = "github.com/grafana/grafana/apps/secret/decrypt/v1beta1;decryptv1beta1";
message SecureValueDecryptRequest {
// The stack_id or org_id.
diff --git a/pkg/apis/secret/v0alpha1/decrypt/decrypt_grpc.pb.go b/apps/secret/decrypt/v1beta1/decrypt_grpc.pb.go
similarity index 97%
rename from pkg/apis/secret/v0alpha1/decrypt/decrypt_grpc.pb.go
rename to apps/secret/decrypt/v1beta1/decrypt_grpc.pb.go
index 9b14a013678..92092215b58 100644
--- a/pkg/apis/secret/v0alpha1/decrypt/decrypt_grpc.pb.go
+++ b/apps/secret/decrypt/v1beta1/decrypt_grpc.pb.go
@@ -4,7 +4,7 @@
// - protoc (unknown)
// source: decrypt.proto
-package decrypt
+package decryptv1beta1
import (
context "context"
@@ -19,7 +19,7 @@ import (
const _ = grpc.SupportPackageIsVersion8
const (
- SecureValueDecrypter_DecryptSecureValues_FullMethodName = "/decrypt.SecureValueDecrypter/DecryptSecureValues"
+ SecureValueDecrypter_DecryptSecureValues_FullMethodName = "/decryptv1beta1.SecureValueDecrypter/DecryptSecureValues"
)
// SecureValueDecrypterClient is the client API for SecureValueDecrypter service.
@@ -97,7 +97,7 @@ func _SecureValueDecrypter_DecryptSecureValues_Handler(srv interface{}, ctx cont
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var SecureValueDecrypter_ServiceDesc = grpc.ServiceDesc{
- ServiceName: "decrypt.SecureValueDecrypter",
+ ServiceName: "decryptv1beta1.SecureValueDecrypter",
HandlerType: (*SecureValueDecrypterServer)(nil),
Methods: []grpc.MethodDesc{
{
diff --git a/apps/secret/go.mod b/apps/secret/go.mod
new file mode 100644
index 00000000000..0c6f4df1e16
--- /dev/null
+++ b/apps/secret/go.mod
@@ -0,0 +1,66 @@
+module github.com/grafana/grafana/apps/secret
+
+go 1.24.4
+
+require (
+ github.com/grafana/grafana-app-sdk v0.39.2
+ github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf
+ github.com/stretchr/testify v1.10.0
+ google.golang.org/grpc v1.73.0
+ google.golang.org/protobuf v1.36.6
+ gopkg.in/yaml.v3 v3.0.1
+ k8s.io/apimachinery v0.33.2
+ k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
+ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
+)
+
+require (
+ 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
+ github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+ github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+ github.com/getkin/kin-openapi v0.132.0 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-openapi/jsonpointer v0.21.0 // indirect
+ github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/go-test/deep v1.1.1 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/google/gnostic-models v0.6.9 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.39.1 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
+ github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
+ github.com/perimeterx/marshmallow v1.1.5 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.64.0 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
+ github.com/x448/float16 v0.8.4 // indirect
+ go.opentelemetry.io/otel v1.36.0 // indirect
+ go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
+ go.opentelemetry.io/otel/trace v1.36.0 // indirect
+ golang.org/x/net v0.41.0 // indirect
+ golang.org/x/oauth2 v0.30.0 // indirect
+ golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/term v0.32.0 // indirect
+ golang.org/x/text v0.26.0 // indirect
+ golang.org/x/time v0.11.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
+ gopkg.in/inf.v0 v0.9.1 // indirect
+ k8s.io/client-go v0.33.2 // indirect
+ k8s.io/klog/v2 v2.130.1 // indirect
+ sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+ sigs.k8s.io/randfill v1.0.0 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
+ sigs.k8s.io/yaml v1.4.0 // indirect
+)
diff --git a/apps/secret/go.sum b/apps/secret/go.sum
new file mode 100644
index 00000000000..fb88ea01837
--- /dev/null
+++ b/apps/secret/go.sum
@@ -0,0 +1,189 @@
+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/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=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
+github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
+github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
+github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmFFu/G98Xh8=
+github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
+github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
+github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
+github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf h1:BBGDHffvVNLoYQlXEpbXcxE0vbpq7pm/8OWF5I+UDZg=
+github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+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/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.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
+github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
+github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
+github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
+github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
+github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
+github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+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=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
+go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
+go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
+go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
+go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
+go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
+go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
+go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
+go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
+go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
+golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
+golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
+golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
+golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
+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.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
+golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
+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=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
+google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
+gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
+k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
+k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
+k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
+k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
+k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
+sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
+sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
+sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
+sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff --git a/apps/secret/kinds/cue.mod/module.cue b/apps/secret/kinds/cue.mod/module.cue
new file mode 100644
index 00000000000..bad5ef304e1
--- /dev/null
+++ b/apps/secret/kinds/cue.mod/module.cue
@@ -0,0 +1,4 @@
+module: "github.com/grafana/grafana/apps/secret/kinds"
+language: {
+ version: "v0.9.0"
+}
diff --git a/apps/secret/kinds/keeper.cue b/apps/secret/kinds/keeper.cue
new file mode 100644
index 00000000000..117e3bbd8a3
--- /dev/null
+++ b/apps/secret/kinds/keeper.cue
@@ -0,0 +1,26 @@
+package secret
+
+import "github.com/grafana/grafana/apps/secret/kinds/v1beta1"
+
+keeper: {
+ kind: "Keeper"
+ pluralName: "Keepers"
+ current: "v1beta1"
+ scope: "Namespaced"
+ current: "v1beta1"
+ codegen: {
+ ts: {
+ enabled: false
+ }
+ go: {
+ enabled: true
+ }
+ }
+ versions: {
+ "v1beta1": {
+ schema: {
+ spec: v1beta1.KeeperSpec
+ }
+ }
+ }
+}
diff --git a/apps/secret/kinds/manifest.cue b/apps/secret/kinds/manifest.cue
new file mode 100644
index 00000000000..1f288bcd328
--- /dev/null
+++ b/apps/secret/kinds/manifest.cue
@@ -0,0 +1,10 @@
+package secret
+
+manifest: {
+ appName: "secret"
+ groupOverride: "secret.grafana.app"
+ kinds: [
+ securevalue,
+ keeper,
+ ]
+}
diff --git a/apps/secret/kinds/securevalue.cue b/apps/secret/kinds/securevalue.cue
new file mode 100644
index 00000000000..6bed093f46d
--- /dev/null
+++ b/apps/secret/kinds/securevalue.cue
@@ -0,0 +1,27 @@
+package secret
+
+import "github.com/grafana/grafana/apps/secret/kinds/v1beta1"
+
+securevalue: {
+ kind: "SecureValue"
+ pluralName: "SecureValues"
+ current: "v1beta1"
+ scope: "Namespaced"
+ current: "v1beta1"
+ codegen: {
+ ts: {
+ enabled: false
+ }
+ go: {
+ enabled: true
+ }
+ }
+ versions: {
+ "v1beta1": {
+ schema: {
+ spec: v1beta1.SecureValueSpec
+ status: v1beta1.SecureValueStatus
+ }
+ }
+ }
+}
diff --git a/apps/secret/kinds/v1beta1/keeper.cue b/apps/secret/kinds/v1beta1/keeper.cue
new file mode 100644
index 00000000000..36e20198ab7
--- /dev/null
+++ b/apps/secret/kinds/v1beta1/keeper.cue
@@ -0,0 +1,68 @@
+package v1beta1
+
+import "strings"
+
+KeeperSpec: {
+ // Short description for the Keeper.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=253
+ description: string & strings.MinRunes(1) & strings.MaxRunes(253)
+
+ // AWS Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ aws?: #AWSConfig
+
+ // Azure Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ azure?: #AzureConfig
+
+ // GCP Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ gcp?: #GCPConfig
+
+ // HashiCorp Vault Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ hashiCorpVault?: #HashiCorpConfig
+}
+
+#AWSConfig: {
+ accessKeyID: #CredentialValue
+ secretAccessKey: #CredentialValue
+ kmsKeyID?: string
+}
+
+#AzureConfig: {
+ keyVaultName: string
+ tenantID: string
+ clientID: string
+ clientSecret: #CredentialValue
+}
+
+#GCPConfig: {
+ projectID: string
+ credentialsFile: string
+}
+
+#HashiCorpConfig: {
+ address: string
+ token: #CredentialValue
+}
+
+#CredentialValue: {
+ // The name of the secure value that holds the actual value.
+ // +optional
+ secureValueName: string
+
+ // The value is taken from the environment variable.
+ // +optional
+ valueFromEnv: string
+
+ // The value is taken from the Grafana config file.
+ // TODO: how do we explain that this is a path to the config file?
+ // +optional
+ valueFromConfig: string
+}
diff --git a/apps/secret/kinds/v1beta1/securevalue.cue b/apps/secret/kinds/v1beta1/securevalue.cue
new file mode 100644
index 00000000000..9fef8e63f46
--- /dev/null
+++ b/apps/secret/kinds/v1beta1/securevalue.cue
@@ -0,0 +1,53 @@
+package v1beta1
+
+import (
+ "list"
+ "strings"
+)
+
+// ExposedSecureValue contains the raw decrypted secure value.
+#ExposedSecureValue: string
+
+SecureValueSpec: {
+ // Short description that explains the purpose of this SecureValue.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=25
+ description: string & strings.MinRunes(1) & strings.MaxRunes(25)
+
+ // The raw value is only valid for write. Read/List will always be empty.
+ // There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`.
+ // Minimum and maximum lengths in bytes.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=24576
+ // +optional
+ value?: #ExposedSecureValue
+
+ // When using a third-party keeper, the `ref` is used to reference a value inside the remote storage.
+ // This should not contain sensitive information.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=1024
+ // +optional
+ ref?: string & strings.MinRunes(1) & strings.MaxRunes(1024)
+
+ // Name of the keeper, being the actual storage of the secure value.
+ // If not specified, the default keeper for the namespace will be used.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=253
+ // +optional
+ keeper?: string & strings.MinRunes(1) & strings.MaxRunes(253)
+
+ // The Decrypters that are allowed to decrypt this secret.
+ // An empty list means no service can decrypt it.
+ // +k8s:validation:maxItems=64
+ // +k8s:validation:uniqueItems=true
+ // +listType=atomic
+ // +optional
+ decrypters?: [...string] & list.UniqueItems() & list.MaxItems(64)
+}
+
+SecureValueStatus: {
+ version: int64 & >=0
+
+ // +optional
+ externalID: string
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/constants.go b/apps/secret/pkg/apis/secret/v1beta1/constants.go
new file mode 100644
index 00000000000..2db86acf35b
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/constants.go
@@ -0,0 +1,18 @@
+package v1beta1
+
+import "k8s.io/apimachinery/pkg/runtime/schema"
+
+const (
+ // APIGroup is the API group used by all kinds in this package
+ APIGroup = "secret.grafana.app"
+ // APIVersion is the API version used by all kinds in this package
+ APIVersion = "v1beta1"
+)
+
+var (
+ // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
+ GroupVersion = schema.GroupVersion{
+ Group: APIGroup,
+ Version: APIVersion,
+ }
+)
diff --git a/pkg/apis/secret/v0alpha1/exposed_secure_value.go b/apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value.go
similarity index 91%
rename from pkg/apis/secret/v0alpha1/exposed_secure_value.go
rename to apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value.go
index 1f77cca2112..a8738c3093a 100644
--- a/pkg/apis/secret/v0alpha1/exposed_secure_value.go
+++ b/apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value.go
@@ -1,4 +1,8 @@
-package v0alpha1
+//
+// THIS FILE IS MANUALLY GENERATED TO OVERCOME LIMITATIONS WITH CUE. FEEL FREE TO EDIT IT.
+//
+
+package v1beta1
import (
"encoding/json"
@@ -11,7 +15,7 @@ import (
const redacted = "[REDACTED]"
// ExposedSecureValue contains the raw decrypted secure value.
-type ExposedSecureValue string
+type ExposedSecureValue = SecureValueExposedSecureValue
var (
_ fmt.Stringer = (*ExposedSecureValue)(nil)
diff --git a/pkg/apis/secret/v0alpha1/exposed_secure_value_test.go b/apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value_test.go
similarity index 89%
rename from pkg/apis/secret/v0alpha1/exposed_secure_value_test.go
rename to apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value_test.go
index 1d21e0505bc..90d53bdf7ae 100644
--- a/pkg/apis/secret/v0alpha1/exposed_secure_value_test.go
+++ b/apps/secret/pkg/apis/secret/v1beta1/exposed_secure_value_test.go
@@ -1,4 +1,8 @@
-package v0alpha1_test
+//
+// THIS FILE IS MANUALLY GENERATED TO OVERCOME LIMITATIONS WITH CUE. FEEL FREE TO EDIT IT.
+//
+
+package v1beta1
import (
"bytes"
@@ -6,7 +10,6 @@ import (
"fmt"
"testing"
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
@@ -15,7 +18,7 @@ func TestExposedSecureValue(t *testing.T) {
expected := "[REDACTED]"
rawValue := "a-password"
- esv := v0alpha1.NewExposedSecureValue(rawValue)
+ esv := NewExposedSecureValue(rawValue)
// String must not return the exposed secure value.
require.Equal(t, expected, esv.String())
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_codec_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_codec_gen.go
new file mode 100644
index 00000000000..1a4f6fb2704
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// KeeperJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type KeeperJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*KeeperJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*KeeperJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &KeeperJSONCodec{}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_metadata_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_metadata_gen.go
new file mode 100644
index 00000000000..82bd4258403
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type KeeperMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewKeeperMetadata creates a new KeeperMetadata object.
+func NewKeeperMetadata() *KeeperMetadata {
+ return &KeeperMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_object_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_object_gen.go
new file mode 100644
index 00000000000..f75d6299345
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type Keeper struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the Keeper
+ Spec KeeperSpec `json:"spec" yaml:"spec"`
+
+ Status KeeperStatus `json:"status" yaml:"status"`
+}
+
+func (o *Keeper) GetSpec() any {
+ return o.Spec
+}
+
+func (o *Keeper) SetSpec(spec any) error {
+ cast, ok := spec.(KeeperSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *Keeper) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *Keeper) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *Keeper) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(KeeperStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type KeeperStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *Keeper) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *Keeper) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *Keeper) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *Keeper) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *Keeper) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *Keeper) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *Keeper) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *Keeper) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *Keeper) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *Keeper) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *Keeper) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *Keeper) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *Keeper) DeepCopy() *Keeper {
+ cpy := &Keeper{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *Keeper) DeepCopyInto(dst *Keeper) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &Keeper{}
+
+// +k8s:openapi-gen=true
+type KeeperList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []Keeper `json:"items" yaml:"items"`
+}
+
+func (o *KeeperList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *KeeperList) Copy() resource.ListObject {
+ cpy := &KeeperList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]Keeper, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*Keeper); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *KeeperList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *KeeperList) SetItems(items []resource.Object) {
+ o.Items = make([]Keeper, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*Keeper)
+ }
+}
+
+func (o *KeeperList) DeepCopy() *KeeperList {
+ cpy := &KeeperList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *KeeperList) DeepCopyInto(dst *KeeperList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &KeeperList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *KeeperSpec) DeepCopy() *KeeperSpec {
+ cpy := &KeeperSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *KeeperSpec) DeepCopyInto(dst *KeeperSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of KeeperStatus
+func (s *KeeperStatus) DeepCopy() *KeeperStatus {
+ cpy := &KeeperStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies KeeperStatus into another KeeperStatus object
+func (s *KeeperStatus) DeepCopyInto(dst *KeeperStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_schema_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_schema_gen.go
new file mode 100644
index 00000000000..b2ef185503e
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaKeeper = resource.NewSimpleSchema("secret.grafana.app", "v1beta1", &Keeper{}, &KeeperList{}, resource.WithKind("Keeper"),
+ resource.WithPlural("keepers"), resource.WithScope(resource.NamespacedScope))
+ kindKeeper = resource.Kind{
+ Schema: schemaKeeper,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &KeeperJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func KeeperKind() resource.Kind {
+ return kindKeeper
+}
+
+// Schema returns a resource.SimpleSchema representation of Keeper
+func KeeperSchema() *resource.SimpleSchema {
+ return schemaKeeper
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindKeeper
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_spec_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_spec_gen.go
new file mode 100644
index 00000000000..76d232465c8
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_spec_gen.go
@@ -0,0 +1,105 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+// +k8s:openapi-gen=true
+type KeeperAWSConfig struct {
+ AccessKeyID KeeperCredentialValue `json:"accessKeyID"`
+ SecretAccessKey KeeperCredentialValue `json:"secretAccessKey"`
+ KmsKeyID *string `json:"kmsKeyID,omitempty"`
+}
+
+// NewKeeperAWSConfig creates a new KeeperAWSConfig object.
+func NewKeeperAWSConfig() *KeeperAWSConfig {
+ return &KeeperAWSConfig{
+ AccessKeyID: *NewKeeperCredentialValue(),
+ SecretAccessKey: *NewKeeperCredentialValue(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type KeeperCredentialValue struct {
+ // The name of the secure value that holds the actual value.
+ // +optional
+ SecureValueName string `json:"secureValueName"`
+ // The value is taken from the environment variable.
+ // +optional
+ ValueFromEnv string `json:"valueFromEnv"`
+ // The value is taken from the Grafana config file.
+ // TODO: how do we explain that this is a path to the config file?
+ // +optional
+ ValueFromConfig string `json:"valueFromConfig"`
+}
+
+// NewKeeperCredentialValue creates a new KeeperCredentialValue object.
+func NewKeeperCredentialValue() *KeeperCredentialValue {
+ return &KeeperCredentialValue{}
+}
+
+// +k8s:openapi-gen=true
+type KeeperAzureConfig struct {
+ KeyVaultName string `json:"keyVaultName"`
+ TenantID string `json:"tenantID"`
+ ClientID string `json:"clientID"`
+ ClientSecret KeeperCredentialValue `json:"clientSecret"`
+}
+
+// NewKeeperAzureConfig creates a new KeeperAzureConfig object.
+func NewKeeperAzureConfig() *KeeperAzureConfig {
+ return &KeeperAzureConfig{
+ ClientSecret: *NewKeeperCredentialValue(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type KeeperGCPConfig struct {
+ ProjectID string `json:"projectID"`
+ CredentialsFile string `json:"credentialsFile"`
+}
+
+// NewKeeperGCPConfig creates a new KeeperGCPConfig object.
+func NewKeeperGCPConfig() *KeeperGCPConfig {
+ return &KeeperGCPConfig{}
+}
+
+// +k8s:openapi-gen=true
+type KeeperHashiCorpConfig struct {
+ Address string `json:"address"`
+ Token KeeperCredentialValue `json:"token"`
+}
+
+// NewKeeperHashiCorpConfig creates a new KeeperHashiCorpConfig object.
+func NewKeeperHashiCorpConfig() *KeeperHashiCorpConfig {
+ return &KeeperHashiCorpConfig{
+ Token: *NewKeeperCredentialValue(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type KeeperSpec struct {
+ // Short description for the Keeper.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=253
+ Description string `json:"description"`
+ // AWS Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ Aws *KeeperAWSConfig `json:"aws,omitempty"`
+ // Azure Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ Azure *KeeperAzureConfig `json:"azure,omitempty"`
+ // GCP Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ Gcp *KeeperGCPConfig `json:"gcp,omitempty"`
+ // HashiCorp Vault Keeper Configuration.
+ // +structType=atomic
+ // +optional
+ HashiCorpVault *KeeperHashiCorpConfig `json:"hashiCorpVault,omitempty"`
+}
+
+// NewKeeperSpec creates a new KeeperSpec object.
+func NewKeeperSpec() *KeeperSpec {
+ return &KeeperSpec{}
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_status_gen.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_status_gen.go
new file mode 100644
index 00000000000..033b71b183b
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+// +k8s:openapi-gen=true
+type KeeperstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State KeeperStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewKeeperstatusOperatorState creates a new KeeperstatusOperatorState object.
+func NewKeeperstatusOperatorState() *KeeperstatusOperatorState {
+ return &KeeperstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type KeeperStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]KeeperstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewKeeperStatus creates a new KeeperStatus object.
+func NewKeeperStatus() *KeeperStatus {
+ return &KeeperStatus{}
+}
+
+// +k8s:openapi-gen=true
+type KeeperStatusOperatorStateState string
+
+const (
+ KeeperStatusOperatorStateStateSuccess KeeperStatusOperatorStateState = "success"
+ KeeperStatusOperatorStateStateInProgress KeeperStatusOperatorStateState = "in_progress"
+ KeeperStatusOperatorStateStateFailed KeeperStatusOperatorStateState = "failed"
+)
diff --git a/apps/secret/pkg/apis/secret/v1beta1/keeper_type.go b/apps/secret/pkg/apis/secret/v1beta1/keeper_type.go
new file mode 100644
index 00000000000..0feeac75dd1
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/keeper_type.go
@@ -0,0 +1,63 @@
+//
+// THIS FILE IS MANUALLY GENERATED TO OVERCOME LIMITATIONS WITH CUE. FEEL FREE TO EDIT IT.
+//
+
+package v1beta1
+
+// KeeperType represents the type of a Keeper.
+type KeeperType string
+
+const (
+ AWSKeeperType KeeperType = "aws"
+ AzureKeeperType KeeperType = "azure"
+ GCPKeeperType KeeperType = "gcp"
+ HashiCorpKeeperType KeeperType = "hashicorp"
+)
+
+func (kt KeeperType) String() string {
+ return string(kt)
+}
+
+// KeeperConfig is an interface that all keeper config types must implement.
+type KeeperConfig interface {
+ Type() KeeperType
+}
+
+func (s *KeeperSpec) GetType() KeeperType {
+ if s.Aws != nil {
+ return AWSKeeperType
+ }
+ if s.Azure != nil {
+ return AzureKeeperType
+ }
+ if s.Gcp != nil {
+ return GCPKeeperType
+ }
+ if s.HashiCorpVault != nil {
+ return HashiCorpKeeperType
+ }
+ return ""
+}
+
+// System Keeper.
+type SystemKeeperConfig struct{}
+
+func (*SystemKeeperConfig) Type() KeeperType {
+ return "system"
+}
+
+func (s *KeeperAWSConfig) Type() KeeperType {
+ return AWSKeeperType
+}
+
+func (s *KeeperAzureConfig) Type() KeeperType {
+ return AzureKeeperType
+}
+
+func (s *KeeperGCPConfig) Type() KeeperType {
+ return GCPKeeperType
+}
+
+func (s *KeeperHashiCorpConfig) Type() KeeperType {
+ return HashiCorpKeeperType
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/register.go b/apps/secret/pkg/apis/secret/v1beta1/register.go
new file mode 100644
index 00000000000..32d89abf7d5
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/register.go
@@ -0,0 +1,73 @@
+//
+// THIS FILE IS MANUALLY GENERATED TO OVERCOME LIMITATIONS WITH CUE. FEEL FREE TO EDIT IT.
+//
+
+package v1beta1
+
+import (
+ "fmt"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+
+ "github.com/grafana/grafana/pkg/apimachinery/utils"
+)
+
+var SecureValuesResourceInfo = utils.NewResourceInfo(
+ APIGroup, APIVersion,
+ "securevalues", "securevalue", "SecureValue",
+ func() runtime.Object { return &SecureValue{} },
+ func() runtime.Object { return &SecureValueList{} },
+ utils.TableColumns{
+ Definition: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string", Format: "name"},
+ {Name: "Description", Type: "string", Format: "string", Description: "Short description that explains the purpose of this SecureValue"},
+ {Name: "Keeper", Type: "string", Format: "string", Description: "Storage of the secure value"},
+ {Name: "Ref", Type: "string", Format: "string", Description: "If present, the reference to a secret"},
+ },
+ Reader: func(obj any) ([]any, error) {
+ if r, ok := obj.(*SecureValue); ok {
+ return []any{r.Name, r.Spec.Description, r.Spec.Keeper, r.Spec.Ref}, nil
+ }
+
+ return nil, fmt.Errorf("expected SecureValue but got %T", obj)
+ },
+ },
+)
+
+var KeeperResourceInfo = utils.NewResourceInfo(
+ APIGroup, APIVersion,
+ "keepers", "keeper", "Keeper",
+ func() runtime.Object { return &Keeper{} },
+ func() runtime.Object { return &KeeperList{} },
+ utils.TableColumns{
+ Definition: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string", Format: "name"},
+ {Name: "Description", Type: "string", Format: "string", Description: "Short description for the Keeper"},
+ },
+ Reader: func(obj any) ([]any, error) {
+ if r, ok := obj.(*Keeper); ok {
+ return []any{r.Name, r.Spec.Description}, nil
+ }
+
+ return nil, fmt.Errorf("expected Keeper but got %T", obj)
+ },
+ },
+)
+
+// SchemeGroupVersion is group version used to register these objects.
+var SchemeGroupVersion = schema.GroupVersion{Group: APIGroup, Version: APIVersion}
+
+// Adds the list of known types to the given scheme.
+func AddKnownTypes(scheme *runtime.Scheme, version string) error {
+ scheme.AddKnownTypes(
+ schema.GroupVersion{Group: APIGroup, Version: version},
+ &SecureValue{},
+ &SecureValueList{},
+ &Keeper{},
+ &KeeperList{},
+ )
+
+ return nil
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_codec_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_codec_gen.go
new file mode 100644
index 00000000000..8e9c88ed873
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// SecureValueJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type SecureValueJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*SecureValueJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*SecureValueJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &SecureValueJSONCodec{}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_metadata_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_metadata_gen.go
new file mode 100644
index 00000000000..c8691021594
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_metadata_gen.go
@@ -0,0 +1,31 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type SecureValueMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewSecureValueMetadata creates a new SecureValueMetadata object.
+func NewSecureValueMetadata() *SecureValueMetadata {
+ return &SecureValueMetadata{
+ Finalizers: []string{},
+ Labels: map[string]string{},
+ }
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_object_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_object_gen.go
new file mode 100644
index 00000000000..c1832e9bca7
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_object_gen.go
@@ -0,0 +1,319 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type SecureValue struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec is the spec of the SecureValue
+ Spec SecureValueSpec `json:"spec" yaml:"spec"`
+
+ Status SecureValueStatus `json:"status" yaml:"status"`
+}
+
+func (o *SecureValue) GetSpec() any {
+ return o.Spec
+}
+
+func (o *SecureValue) SetSpec(spec any) error {
+ cast, ok := spec.(SecureValueSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *SecureValue) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.Status,
+ }
+}
+
+func (o *SecureValue) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.Status, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *SecureValue) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(SecureValueStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type SecureValueStatus", value)
+ }
+ o.Status = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *SecureValue) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *SecureValue) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *SecureValue) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *SecureValue) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *SecureValue) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *SecureValue) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *SecureValue) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *SecureValue) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *SecureValue) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *SecureValue) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *SecureValue) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *SecureValue) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *SecureValue) DeepCopy() *SecureValue {
+ cpy := &SecureValue{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *SecureValue) DeepCopyInto(dst *SecureValue) {
+ dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
+ dst.TypeMeta.Kind = o.TypeMeta.Kind
+ o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
+ o.Spec.DeepCopyInto(&dst.Spec)
+ o.Status.DeepCopyInto(&dst.Status)
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &SecureValue{}
+
+// +k8s:openapi-gen=true
+type SecureValueList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []SecureValue `json:"items" yaml:"items"`
+}
+
+func (o *SecureValueList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *SecureValueList) Copy() resource.ListObject {
+ cpy := &SecureValueList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]SecureValue, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*SecureValue); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *SecureValueList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *SecureValueList) SetItems(items []resource.Object) {
+ o.Items = make([]SecureValue, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*SecureValue)
+ }
+}
+
+func (o *SecureValueList) DeepCopy() *SecureValueList {
+ cpy := &SecureValueList{}
+ o.DeepCopyInto(cpy)
+ return cpy
+}
+
+func (o *SecureValueList) DeepCopyInto(dst *SecureValueList) {
+ resource.CopyObjectInto(dst, o)
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &SecureValueList{}
+
+// Copy methods for all subresource types
+
+// DeepCopy creates a full deep copy of Spec
+func (s *SecureValueSpec) DeepCopy() *SecureValueSpec {
+ cpy := &SecureValueSpec{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies Spec into another Spec object
+func (s *SecureValueSpec) DeepCopyInto(dst *SecureValueSpec) {
+ resource.CopyObjectInto(dst, s)
+}
+
+// DeepCopy creates a full deep copy of SecureValueStatus
+func (s *SecureValueStatus) DeepCopy() *SecureValueStatus {
+ cpy := &SecureValueStatus{}
+ s.DeepCopyInto(cpy)
+ return cpy
+}
+
+// DeepCopyInto deep copies SecureValueStatus into another SecureValueStatus object
+func (s *SecureValueStatus) DeepCopyInto(dst *SecureValueStatus) {
+ resource.CopyObjectInto(dst, s)
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_schema_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_schema_gen.go
new file mode 100644
index 00000000000..4a978fe34b6
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v1beta1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaSecureValue = resource.NewSimpleSchema("secret.grafana.app", "v1beta1", &SecureValue{}, &SecureValueList{}, resource.WithKind("SecureValue"),
+ resource.WithPlural("securevalues"), resource.WithScope(resource.NamespacedScope))
+ kindSecureValue = resource.Kind{
+ Schema: schemaSecureValue,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &SecureValueJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func SecureValueKind() resource.Kind {
+ return kindSecureValue
+}
+
+// Schema returns a resource.SimpleSchema representation of SecureValue
+func SecureValueSchema() *resource.SimpleSchema {
+ return schemaSecureValue
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindSecureValue
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_spec_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_spec_gen.go
new file mode 100644
index 00000000000..1b5d0956893
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_spec_gen.go
@@ -0,0 +1,46 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+// ExposedSecureValue contains the raw decrypted secure value.
+// +k8s:openapi-gen=true
+type SecureValueExposedSecureValue string
+
+// +k8s:openapi-gen=true
+type SecureValueSpec struct {
+ // Short description that explains the purpose of this SecureValue.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=25
+ Description string `json:"description"`
+ // The raw value is only valid for write. Read/List will always be empty.
+ // There is no support for mixing `value` and `ref`, you can't create a secret in a third-party keeper with a specified `ref`.
+ // Minimum and maximum lengths in bytes.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=24576
+ // +optional
+ Value *SecureValueExposedSecureValue `json:"value,omitempty"`
+ // When using a third-party keeper, the `ref` is used to reference a value inside the remote storage.
+ // This should not contain sensitive information.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=1024
+ // +optional
+ Ref *string `json:"ref,omitempty"`
+ // Name of the keeper, being the actual storage of the secure value.
+ // If not specified, the default keeper for the namespace will be used.
+ // +k8s:validation:minLength=1
+ // +k8s:validation:maxLength=253
+ // +optional
+ Keeper *string `json:"keeper,omitempty"`
+ // The Decrypters that are allowed to decrypt this secret.
+ // An empty list means no service can decrypt it.
+ // +k8s:validation:maxItems=64
+ // +k8s:validation:uniqueItems=true
+ // +listType=atomic
+ // +optional
+ Decrypters []string `json:"decrypters,omitempty"`
+}
+
+// NewSecureValueSpec creates a new SecureValueSpec object.
+func NewSecureValueSpec() *SecureValueSpec {
+ return &SecureValueSpec{}
+}
diff --git a/apps/secret/pkg/apis/secret/v1beta1/securevalue_status_gen.go b/apps/secret/pkg/apis/secret/v1beta1/securevalue_status_gen.go
new file mode 100644
index 00000000000..eac159c6035
--- /dev/null
+++ b/apps/secret/pkg/apis/secret/v1beta1/securevalue_status_gen.go
@@ -0,0 +1,47 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v1beta1
+
+// +k8s:openapi-gen=true
+type SecureValuestatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State SecureValueStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewSecureValuestatusOperatorState creates a new SecureValuestatusOperatorState object.
+func NewSecureValuestatusOperatorState() *SecureValuestatusOperatorState {
+ return &SecureValuestatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type SecureValueStatus struct {
+ Version int64 `json:"version"`
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]SecureValuestatusOperatorState `json:"operatorStates,omitempty"`
+ // +optional
+ ExternalID string `json:"externalID"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewSecureValueStatus creates a new SecureValueStatus object.
+func NewSecureValueStatus() *SecureValueStatus {
+ return &SecureValueStatus{}
+}
+
+// +k8s:openapi-gen=true
+type SecureValueStatusOperatorStateState string
+
+const (
+ SecureValueStatusOperatorStateStateSuccess SecureValueStatusOperatorStateState = "success"
+ SecureValueStatusOperatorStateStateInProgress SecureValueStatusOperatorStateState = "in_progress"
+ SecureValueStatusOperatorStateStateFailed SecureValueStatusOperatorStateState = "failed"
+)
diff --git a/pkg/apis/secret/v0alpha1/zz_generated.openapi.go b/apps/secret/pkg/apis/secret/v1beta1/zz_openapi_gen.go
similarity index 55%
rename from pkg/apis/secret/v0alpha1/zz_generated.openapi.go
rename to apps/secret/pkg/apis/secret/v1beta1/zz_openapi_gen.go
index de1934c36cb..87ba7504932 100644
--- a/pkg/apis/secret/v0alpha1/zz_generated.openapi.go
+++ b/apps/secret/pkg/apis/secret/v1beta1/zz_openapi_gen.go
@@ -1,11 +1,9 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
-// SPDX-License-Identifier: AGPL-3.0-only
+// Code generated by grafana-app-sdk. DO NOT EDIT.
-// Code generated by openapi-gen. DO NOT EDIT.
-
-package v0alpha1
+package v1beta1
import (
common "k8s.io/kube-openapi/pkg/common"
@@ -15,95 +13,106 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AWSCredentials": schema_pkg_apis_secret_v0alpha1_AWSCredentials(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AWSKeeperConfig": schema_pkg_apis_secret_v0alpha1_AWSKeeperConfig(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AzureCredentials": schema_pkg_apis_secret_v0alpha1_AzureCredentials(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AzureKeeperConfig": schema_pkg_apis_secret_v0alpha1_AzureKeeperConfig(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue": schema_pkg_apis_secret_v0alpha1_CredentialValue(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.GCPCredentials": schema_pkg_apis_secret_v0alpha1_GCPCredentials(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.GCPKeeperConfig": schema_pkg_apis_secret_v0alpha1_GCPKeeperConfig(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.HashiCorpCredentials": schema_pkg_apis_secret_v0alpha1_HashiCorpCredentials(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.HashiCorpKeeperConfig": schema_pkg_apis_secret_v0alpha1_HashiCorpKeeperConfig(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.Keeper": schema_pkg_apis_secret_v0alpha1_Keeper(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.KeeperList": schema_pkg_apis_secret_v0alpha1_KeeperList(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.KeeperSpec": schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValue": schema_pkg_apis_secret_v0alpha1_SecureValue(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueList": schema_pkg_apis_secret_v0alpha1_SecureValueList(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueSpec": schema_pkg_apis_secret_v0alpha1_SecureValueSpec(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueStatus": schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref),
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SystemKeeperConfig": schema_pkg_apis_secret_v0alpha1_SystemKeeperConfig(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.Keeper": schema_pkg_apis_secret_v1beta1_Keeper(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAWSConfig": schema_pkg_apis_secret_v1beta1_KeeperAWSConfig(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAzureConfig": schema_pkg_apis_secret_v1beta1_KeeperAzureConfig(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue": schema_pkg_apis_secret_v1beta1_KeeperCredentialValue(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperGCPConfig": schema_pkg_apis_secret_v1beta1_KeeperGCPConfig(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperHashiCorpConfig": schema_pkg_apis_secret_v1beta1_KeeperHashiCorpConfig(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperList": schema_pkg_apis_secret_v1beta1_KeeperList(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperSpec": schema_pkg_apis_secret_v1beta1_KeeperSpec(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperStatus": schema_pkg_apis_secret_v1beta1_KeeperStatus(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperstatusOperatorState": schema_pkg_apis_secret_v1beta1_KeeperstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValue": schema_pkg_apis_secret_v1beta1_SecureValue(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueList": schema_pkg_apis_secret_v1beta1_SecureValueList(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueSpec": schema_pkg_apis_secret_v1beta1_SecureValueSpec(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueStatus": schema_pkg_apis_secret_v1beta1_SecureValueStatus(ref),
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValuestatusOperatorState": schema_pkg_apis_secret_v1beta1_SecureValuestatusOperatorState(ref),
}
}
-func schema_pkg_apis_secret_v0alpha1_AWSCredentials(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_Keeper(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
- Description: "Credentials of remote keepers.",
- Type: []string{"object"},
+ Type: []string{"object"},
Properties: map[string]spec.Schema{
- "accessKeyId": {
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the Keeper",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperSpec", "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_secret_v1beta1_KeeperAWSConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "accessKeyID": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"),
},
},
"secretAccessKey": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"),
},
},
- "kmsKeyId": {
+ "kmsKeyID": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
- Required: []string{"accessKeyId", "secretAccessKey"},
+ Required: []string{"accessKeyID", "secretAccessKey"},
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"},
}
}
-func schema_pkg_apis_secret_v0alpha1_AWSKeeperConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "Remote Keepers.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "accessKeyId": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
- },
- },
- "secretAccessKey": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
- },
- },
- "kmsKeyId": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"accessKeyId", "secretAccessKey"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_AzureCredentials(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperAzureConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -116,14 +125,14 @@ func schema_pkg_apis_secret_v0alpha1_AzureCredentials(ref common.ReferenceCallba
Format: "",
},
},
- "tenantId": {
+ "tenantID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
- "clientId": {
+ "clientID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
@@ -133,70 +142,28 @@ func schema_pkg_apis_secret_v0alpha1_AzureCredentials(ref common.ReferenceCallba
"clientSecret": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"),
},
},
},
- Required: []string{"keyVaultName", "tenantId", "clientId", "clientSecret"},
+ Required: []string{"keyVaultName", "tenantID", "clientID", "clientSecret"},
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"},
}
}
-func schema_pkg_apis_secret_v0alpha1_AzureKeeperConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperCredentialValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "keyVaultName": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "tenantId": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "clientId": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "clientSecret": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
- },
- },
- },
- Required: []string{"keyVaultName", "tenantId", "clientId", "clientSecret"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_CredentialValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "Holds the way credentials are obtained.",
- Type: []string{"object"},
Properties: map[string]spec.Schema{
"secureValueName": {
SchemaProps: spec.SchemaProps{
Description: "The name of the secure value that holds the actual value.",
+ Default: "",
Type: []string{"string"},
Format: "",
},
@@ -204,6 +171,7 @@ func schema_pkg_apis_secret_v0alpha1_CredentialValue(ref common.ReferenceCallbac
"valueFromEnv": {
SchemaProps: spec.SchemaProps{
Description: "The value is taken from the environment variable.",
+ Default: "",
Type: []string{"string"},
Format: "",
},
@@ -211,36 +179,24 @@ func schema_pkg_apis_secret_v0alpha1_CredentialValue(ref common.ReferenceCallbac
"valueFromConfig": {
SchemaProps: spec.SchemaProps{
Description: "The value is taken from the Grafana config file.",
+ Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-unions": []interface{}{
- map[string]interface{}{
- "fields-to-discriminateBy": map[string]interface{}{
- "secureValueName": "SecureValueName",
- "valueFromConfig": "ValueFromConfig",
- "valueFromEnv": "ValueFromEnv",
- },
- },
- },
- },
- },
},
}
}
-func schema_pkg_apis_secret_v0alpha1_GCPCredentials(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperGCPConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
- "projectId": {
+ "projectID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
@@ -255,40 +211,13 @@ func schema_pkg_apis_secret_v0alpha1_GCPCredentials(ref common.ReferenceCallback
},
},
},
- Required: []string{"projectId", "credentialsFile"},
+ Required: []string{"projectID", "credentialsFile"},
},
},
}
}
-func schema_pkg_apis_secret_v0alpha1_GCPKeeperConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "projectId": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "credentialsFile": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"projectId", "credentialsFile"},
- },
- },
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_HashiCorpCredentials(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperHashiCorpConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -304,7 +233,7 @@ func schema_pkg_apis_secret_v0alpha1_HashiCorpCredentials(ref common.ReferenceCa
"token": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"),
},
},
},
@@ -312,39 +241,11 @@ func schema_pkg_apis_secret_v0alpha1_HashiCorpCredentials(ref common.ReferenceCa
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperCredentialValue"},
}
}
-func schema_pkg_apis_secret_v0alpha1_HashiCorpKeeperConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "address": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "token": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"),
- },
- },
- },
- Required: []string{"address", "token"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.CredentialValue"},
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_Keeper(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -366,84 +267,33 @@ func schema_pkg_apis_secret_v0alpha1_Keeper(ref common.ReferenceCallback) common
},
"metadata": {
SchemaProps: spec.SchemaProps{
- Description: "Standard object's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
- },
- },
- "spec": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-patch-merge-key": "name",
- "x-kubernetes-patch-strategy": "replace",
- },
- },
- SchemaProps: spec.SchemaProps{
- Description: "This is the actual keeper schema.",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.KeeperSpec"),
- },
- },
- },
- Required: []string{"spec"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.KeeperSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_KeeperList(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "kind": {
- SchemaProps: spec.SchemaProps{
- Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
- Type: []string{"string"},
- Format: "",
- },
- },
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
- Type: []string{"string"},
- Format: "",
- },
- },
- "metadata": {
- SchemaProps: spec.SchemaProps{
- Description: "Standard list's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
- Description: "Slice containing all keepers.",
- Type: []string{"array"},
+ Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.Keeper"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.Keeper"),
},
},
},
},
},
},
- Required: []string{"items"},
+ Required: []string{"metadata", "items"},
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.Keeper", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.Keeper", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
-func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -467,10 +317,10 @@ func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) co
},
SchemaProps: spec.SchemaProps{
Description: "AWS Keeper Configuration.",
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AWSKeeperConfig"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAWSConfig"),
},
},
- "azurekeyvault": {
+ "azure": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-map-type": "atomic",
@@ -478,7 +328,7 @@ func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) co
},
SchemaProps: spec.SchemaProps{
Description: "Azure Keeper Configuration.",
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AzureKeeperConfig"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAzureConfig"),
},
},
"gcp": {
@@ -489,10 +339,10 @@ func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) co
},
SchemaProps: spec.SchemaProps{
Description: "GCP Keeper Configuration.",
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.GCPKeeperConfig"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperGCPConfig"),
},
},
- "hashivault": {
+ "hashiCorpVault": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-map-type": "atomic",
@@ -500,7 +350,7 @@ func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) co
},
SchemaProps: spec.SchemaProps{
Description: "HashiCorp Vault Keeper Configuration.",
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.HashiCorpKeeperConfig"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperHashiCorpConfig"),
},
},
},
@@ -508,111 +358,202 @@ func schema_pkg_apis_secret_v0alpha1_KeeperSpec(ref common.ReferenceCallback) co
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AWSKeeperConfig", "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.AzureKeeperConfig", "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.GCPKeeperConfig", "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.HashiCorpKeeperConfig"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAWSConfig", "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperAzureConfig", "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperGCPConfig", "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperHashiCorpConfig"},
}
}
-func schema_pkg_apis_secret_v0alpha1_SecureValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
- "kind": {
+ "operatorStates": {
SchemaProps: spec.SchemaProps{
- Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
- Type: []string{"string"},
- Format: "",
- },
- },
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
- Type: []string{"string"},
- Format: "",
- },
- },
- "metadata": {
- SchemaProps: spec.SchemaProps{
- Description: "Standard object's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
- },
- },
- "spec": {
- SchemaProps: spec.SchemaProps{
- Description: "This is the actual secure value schema.",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueSpec"),
- },
- },
- "status": {
- SchemaProps: spec.SchemaProps{
- Description: "Read-only observed status of the `SecureValue`. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueStatus"),
- },
- },
- },
- Required: []string{"spec"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueSpec", "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValueStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
- }
-}
-
-func schema_pkg_apis_secret_v0alpha1_SecureValueList(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "kind": {
- SchemaProps: spec.SchemaProps{
- Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
- Type: []string{"string"},
- Format: "",
- },
- },
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
- Type: []string{"string"},
- Format: "",
- },
- },
- "metadata": {
- SchemaProps: spec.SchemaProps{
- Description: "Standard list's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
- },
- },
- "items": {
- SchemaProps: spec.SchemaProps{
- Description: "Slice containing all secure values. This will NOT output decrypted values.",
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValue"),
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
},
},
},
},
},
},
- Required: []string{"items"},
},
},
Dependencies: []string{
- "github.com/grafana/grafana/pkg/apis/secret/v0alpha1.SecureValue", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.KeeperstatusOperatorState"},
}
}
-func schema_pkg_apis_secret_v0alpha1_SecureValueSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_KeeperstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_secret_v1beta1_SecureValue(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Spec is the spec of the SecureValue",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueSpec", "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValueStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_secret_v1beta1_SecureValueList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValue"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValue", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_secret_v1beta1_SecureValueSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -623,7 +564,7 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueSpec(ref common.ReferenceCallbac
Description: "Short description that explains the purpose of this SecureValue.",
Default: "",
MinLength: ptr.To[int64](1),
- MaxLength: ptr.To[int64](253),
+ MaxLength: ptr.To[int64](25),
Type: []string{"string"},
Format: "",
},
@@ -684,47 +625,111 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueSpec(ref common.ReferenceCallbac
}
}
-func schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_SecureValueStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
- "phase": {
+ "version": {
SchemaProps: spec.SchemaProps{
- Description: "High-level summary of where the `SecureValue` is in its lifecycle. One of: `Pending`, `Succeeded` or `Failed`.\n\nPossible enum values:\n - `\"Failed\"` If the creation of the secret fails, it will move to the `Failed` phase. Check the additional `status` fields for more information on what caused the failure. This state is unrecoverable.\n - `\"Pending\"` When the `SecureValue` is created, it will start in `Pending` phase to create the underlying secret asynchronously.\n - `\"Succeeded\"` If the creation of the secret is successful, it will move to the `Succeeded` phase.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- Enum: []interface{}{"Failed", "Pending", "Succeeded"},
+ Default: 0,
+ Type: []string{"integer"},
+ Format: "int64",
},
},
- "message": {
+ "operatorStates": {
SchemaProps: spec.SchemaProps{
- Description: "A human readable message indicating details about why the `SecureValue` is in this phase. Only applicable if the `phase=Failed`.",
- Type: []string{"string"},
- Format: "",
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValuestatusOperatorState"),
+ },
+ },
+ },
},
},
- "externalId": {
+ "externalID": {
SchemaProps: spec.SchemaProps{
- Type: []string{"string"},
- Format: "",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
},
},
},
- Required: []string{"phase"},
+ Required: []string{"version"},
},
},
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1.SecureValuestatusOperatorState"},
}
}
-func schema_pkg_apis_secret_v0alpha1_SystemKeeperConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
+func schema_pkg_apis_secret_v1beta1_SecureValuestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
- Description: "System Keeper.",
- Type: []string{"object"},
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
},
},
}
diff --git a/apps/secret/pkg/apis/secret_manifest.go b/apps/secret/pkg/apis/secret_manifest.go
new file mode 100644
index 00000000000..12138bbf57b
--- /dev/null
+++ b/apps/secret/pkg/apis/secret_manifest.go
@@ -0,0 +1,65 @@
+//
+// This file is generated by grafana-app-sdk
+// DO NOT EDIT
+//
+
+package apis
+
+import (
+ "fmt"
+
+ "github.com/grafana/grafana-app-sdk/app"
+ "github.com/grafana/grafana-app-sdk/resource"
+
+ v1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
+)
+
+var ()
+
+var appManifestData = app.ManifestData{
+ AppName: "secret",
+ Group: "secret.grafana.app",
+ Kinds: []app.ManifestKind{
+ {
+ Kind: "SecureValue",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v1beta1",
+ },
+ },
+ },
+
+ {
+ Kind: "Keeper",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v1beta1",
+ },
+ },
+ },
+ },
+}
+
+func LocalManifest() app.Manifest {
+ return app.NewEmbeddedManifest(appManifestData)
+}
+
+func RemoteManifest() app.Manifest {
+ return app.NewAPIServerManifest("secret")
+}
+
+var kindVersionToGoType = map[string]resource.Kind{
+ "SecureValue/v1beta1": v1beta1.SecureValueKind(),
+ "Keeper/v1beta1": v1beta1.KeeperKind(),
+}
+
+// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
+// If there is no association for the provided Kind and Version, exists will return false.
+func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) {
+ goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)]
+ return goType, exists
+}
diff --git a/conf/defaults.ini b/conf/defaults.ini
index bc43af809ac..ad0c3276a4a 100644
--- a/conf/defaults.ini
+++ b/conf/defaults.ini
@@ -1121,7 +1121,7 @@ content_types = text/html
# Use space to separate multiple modes, e.g. "console file"
mode = console file
-# Either "debug", "info", "warn", "error", "critical", default is "info"
+# Either "debug", "info", "warn", "error". Default is "info"
level = info
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
@@ -2018,8 +2018,7 @@ provider = static
[feature_toggles.openfeature.context]
# This is EXPERIMENTAL. Please, do not use this section
-# instance = "grafana"
-# version = 11.0.0
+# foo = bar
[date_formats]
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
@@ -2172,12 +2171,12 @@ alert_rules_state = "paused"
###################################### Secrets Manager ######################################
[secrets_manager]
-# Used for signing
+# Current key provider used for envelope encryption
+encryption_provider = secret_key.v1
+
+[secrets_manager.encryption.secret_key.v1]
+# Used to encrypt data keys
secret_key = SW2YcwTIb9zpOOhoPsMm
-# Current key provider used for envelope encryption, default to static value specified by secret_key
-encryption_provider = secretKey.v1
-# List of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1
-available_encryption_providers =
################################## Frontend development configuration ###################################
# Warning! Any settings placed in this section will be available on `process.env.frontend_dev_{foo}` within frontend code
diff --git a/conf/sample.ini b/conf/sample.ini
index 42642479375..238162d2590 100644
--- a/conf/sample.ini
+++ b/conf/sample.ini
@@ -1105,7 +1105,7 @@
# Use space to separate multiple modes, e.g. "console file"
;mode = console file
-# Either "debug", "info", "warn", "error", "critical", default is "info"
+# Either "debug", "info", "warn", "error". Default is "info"
;level = info
# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
diff --git a/contribute/ISSUE_TRIAGE.md b/contribute/ISSUE_TRIAGE.md
index ed9d6c9418e..b856798fb5c 100644
--- a/contribute/ISSUE_TRIAGE.md
+++ b/contribute/ISSUE_TRIAGE.md
@@ -2,61 +2,43 @@
The main goal of issue triage is to categorize all incoming Grafana issues and make sure each issue has all the essential information needed for anyone to understand and be able to start working on it.
-> **Note:** This information is for Grafana project Maintainers, Owners, and Admins. If you are a Contributor, then you won't be able to perform most of the tasks in this topic.
+> [!NOTE]
+> This information is for Grafana project Maintainers, Owners, and Admins. If you are a Contributor, then you won't be able to perform most of the tasks in this topic.
The core maintainers of the Grafana project are responsible for categorizing all incoming issues and delegating any critical or important issue to other maintainers. Currently, one maintainer each week is responsible. Besides that part, triage provides an important way to contribute to an open source project.
## Simplified flowchart diagram of the issue triage process
-
-
-```
- +-------------------+
- | |
- | new issue/ | +
- | more info added |
- | |
- +---------|---------+
- |
- +-------------|-----------+
- | |
- NO +------- all info needed to ------+ YES
- | | categorize the issue? | |
- | | | |
- | +-------------------------+ |
- +------|-----------+ +------------|----------+
- | | | |
- | label: | | label: type/* |
- | needs more info | | label: area/* |
- | | | label: datasource/* |
- +------------------+ | | |
- +------------|----------+
- |
- +--------|-------+
- | |
- NO +---------- is duplicate? --------------------+ YES
- | | | |
- | +----------------+ |
- | +----------------|---------------+
- +------|-----+ | |
- | | | add comment: |
- NO +------------ can repro? ------------+ YES | |
- | | | | | /duplicate of # |
- | +------------+ | | |
- | | +--------------------------------+
-+-------------|-------------+ |
-| | +--------|---------+
-| label: | | |
-| triage/needs-confirmation | NO +-------- needs priority? ------+ YES
-| | | | | |
-+-------------|-------------+ | +------------------+ |
- | | |
-+-------------|------+ +-------|--------+ +----------|---------+
-| | | | | |
-| Assign to project ------ Done -------------- label: priority/* |
-| | | | | |
-+--------------------+ +----------------+ +--------------------+
+```mermaid
+flowchart TD
+ A([New issue / more info added])
+ B{All info needed to categorize the issue?}
+ C1([Label: needs more info])
+ C2([Label: type/#42; Label: area/#42; Label: datasource/#42;])
+ D{Is duplicate?}
+ E1([Add comment: /duplicate of #<issue number>])
+ E2{Can repro?}
+ F1([Label: triage/needs-confirmation])
+ F2{Needs priority?}
+ G1([Assign to project])
+ G2([Label: priority/*])
+ H([Done])
+ %% Flow
+ A --> B
+ B -- No --> C1
+ B -- Yes --> C2
+ C2 --> D
+ D -- Yes --> E1
+ D -- No --> E2
+ E2 -- No --> F1
+ E2 -- Yes --> F2
+ F1 --> G1
+ F2 -- No --> H
+ F2 -- Yes --> G2
+ G2 --> H
+ E1 --> H
+ G1 --> H
```
## Key functions of issue triage
@@ -107,7 +89,7 @@ Bug reports should explain what happened, what was expected, and how to reproduc
##### Enhancement requests
-> **Note:** Prior to August, 2023, community-submitted feature requests were submitted as [Github discussions](https://github.com/grafana/grafana/discussions). These are now submitted using the [feature request issue template](https://github.com/grafana/grafana/issues/new?assignees=&labels=type%2Ffeature-request&projects=&template=1-feature_requests.md).
+> **Note:** Prior to August, 2023, community-submitted feature requests were submitted as [GitHub discussions](https://github.com/grafana/grafana/discussions). These are now submitted using the [feature request issue template](https://github.com/grafana/grafana/issues/new?assignees=&labels=type%2Ffeature-request&projects=&template=1-feature_requests.md).
When submitting an enhancement request we ask that users focus on the problem they'd like to solve and why it’s a problem rather than focusing on the solution itself. To facilitate these objectives, the feature requests template includes the following:
diff --git a/contribute/style-guides/e2e-plugins.md b/contribute/style-guides/e2e-plugins.md
index e708281d675..8d6ffaca61a 100644
--- a/contribute/style-guides/e2e-plugins.md
+++ b/contribute/style-guides/e2e-plugins.md
@@ -6,9 +6,9 @@ When end-to-end testing Grafana plugins, a best practice is to use the [`@grafan
## Add end-to-end tests for a core plugin
-You can add Playwright end-to-end tests for plugins to the [`e2e/plugin-e2e`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e) directory.
+You can add Playwright end-to-end tests for plugins to the [`e2e-playwright/plugin-e2e`](https://github.com/grafana/grafana/tree/main/e2e-playwright/plugin-e2e) directory.
-1. Add a new directory that has the name as your plugin [`here`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e). This is the directory where your plugin tests will be kept.
+1. Add a new directory that has the name as your plugin [`here`](https://github.com/grafana/grafana/tree/main/e2e-playwright/plugin-e2e). This is the directory where your plugin tests will be kept.
1. Playwright uses [projects](https://playwright.dev/docs/test-projects) to logically group tests together. All tests in a project share the same configuration.
In the [Playwright config file](https://github.com/grafana/grafana/blob/main/playwright.config.ts), add a new project item. Make sure the `name` and the `testDir` subdirectory match the name of the directory that contains your plugin tests.
diff --git a/devenv/dev-dashboards/panel-table/table_pagination.json b/devenv/dev-dashboards/panel-table/table_pagination.json
index 0bb4758490b..48f5df03f1f 100644
--- a/devenv/dev-dashboards/panel-table/table_pagination.json
+++ b/devenv/dev-dashboards/panel-table/table_pagination.json
@@ -2662,9 +2662,10 @@
}
],
"schemaVersion": 32,
- "tags": [
- "gdev",
- "panel-tests"
+ "tags": [
+ "gdev",
+ "panel-tests",
+ "table"
],
"templating": {
"list": []
@@ -2675,8 +2676,8 @@
},
"timepicker": {},
"timezone": "",
- "title": "Table panel - Pagination",
+ "title": "Panel Tests - Table - Pagination",
"uid": "1YGJxPUnz",
- "version": 2,
+ "version": 3,
"weekStart": ""
-}
\ No newline at end of file
+}
diff --git a/devenv/dev-dashboards/panel-table/table_sparkline_cell.json b/devenv/dev-dashboards/panel-table/table_sparkline_cell.json
index d18488ca89d..24ec5a57326 100644
--- a/devenv/dev-dashboards/panel-table/table_sparkline_cell.json
+++ b/devenv/dev-dashboards/panel-table/table_sparkline_cell.json
@@ -18,22 +18,27 @@
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
+ "id": 1734,
"links": [],
- "liveNow": false,
"panels": [
{
- "datasource": { "type": "testdata" },
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
"fieldConfig": {
"defaults": {
"color": {
- "mode": "thresholds"
+ "fixedColor": "blue",
+ "mode": "shades"
},
"custom": {
"align": "auto",
"cellOptions": {
- "type": "auto"
+ "type": "sparkline"
},
- "inspect": false
+ "inspect": false,
+ "wrapHeaderText": false
},
"mappings": [],
"thresholds": {
@@ -41,7 +46,7 @@
"steps": [
{
"color": "green",
- "value": null
+ "value": 0
},
{
"color": "red",
@@ -53,8 +58,8 @@
"overrides": []
},
"gridPos": {
- "h": 8,
- "w": 12,
+ "h": 16,
+ "w": 8,
"x": 0,
"y": 0
},
@@ -71,14 +76,507 @@
},
"showHeader": true
},
- "pluginVersion": "10.1.0-pre",
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparkline (lines)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "blue",
+ "mode": "shades"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "drawStyle": "bars",
+ "type": "sparkline"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 16,
+ "w": 8,
+ "x": 8,
+ "y": 0
+ },
+ "id": 2,
+ "maxDataPoints": 60,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparklines (bars)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "blue",
+ "mode": "shades"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "drawStyle": "points",
+ "type": "sparkline"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 16,
+ "w": 8,
+ "x": 16,
+ "y": 0
+ },
+ "id": 3,
+ "maxDataPoints": 100,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparklines (points)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "green",
+ "mode": "shades"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "drawStyle": "line",
+ "type": "sparkline"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "areaF2"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 16,
+ "w": 8,
+ "x": 0,
+ "y": 16
+ },
+ "id": 4,
+ "maxDataPoints": 100,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparklines (min=0)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "yellow",
+ "mode": "shades"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "drawStyle": "line",
+ "type": "sparkline"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "max": 100,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "areaF2"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 16,
+ "w": 8,
+ "x": 8,
+ "y": 16
+ },
+ "id": 5,
+ "maxDataPoints": 100,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparklines (max=100)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "purple",
+ "mode": "shades"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "drawStyle": "line",
+ "lineInterpolation": "linear",
+ "type": "sparkline"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "max": 100,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "areaF2"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 16,
+ "w": 8,
+ "x": 16,
+ "y": 16
+ },
+ "id": 6,
+ "maxDataPoints": 100,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
+ "targets": [
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca"
+ },
+ "refId": "A",
+ "scenarioId": "random_walk",
+ "seriesCount": 31
+ }
+ ],
+ "title": "Sparklines (min=0, max=100)",
+ "transformations": [
+ {
+ "id": "timeSeriesTable",
+ "options": {
+ "A": {
+ "timeField": "time"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "grafana-testdata-datasource",
+ "uid": "PD8C576611E62080A"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "inspect": false,
+ "wrapHeaderText": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 8,
+ "x": 0,
+ "y": 32
+ },
+ "id": 7,
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "12.1.0-pre",
"targets": [
{
"csvContent": "time,x\n2023-06-12T05:49:00Z,10\n2023-06-12T07:01:00Z,20\n2023-06-12T08:13:00Z,NaN\n2023-06-12T09:25:00Z,NaN\n2023-06-12T10:37:00Z,NaN\n2023-06-12T11:49:00Z,30\n2023-06-12T13:01:00Z,20\n2023-06-12T14:13:00Z,10\n2023-06-12T15:25:00Z,Inf\n2023-06-12T16:37:00Z,null\n2023-06-12T17:49:00Z,",
- "datasource": {
- "type": "testdata",
- "uid": "PD8C576611E62080A"
- },
"refId": "A",
"scenarioId": "csv_content"
}
@@ -87,26 +585,31 @@
"transformations": [
{
"id": "timeSeriesTable",
- "options": {}
+ "options": {
+ "A": {
+ "stat": "last",
+ "timeField": ""
+ }
+ }
}
],
"type": "table"
}
],
+ "preload": false,
"refresh": "",
- "schemaVersion": 38,
+ "schemaVersion": 41,
"tags": [],
"templating": {
"list": []
},
"time": {
- "from": "2023-06-12T00:00:00.000Z",
- "to": "2023-06-12T18:00:00.000Z"
+ "from": "now-6h",
+ "to": "now"
},
"timepicker": {},
- "timezone": "utc",
- "title": "Table with SparklineCell",
+ "timezone": "",
+ "title": "Panel Tests - Table - Sparklines",
"uid": "d6373b49-1957-4f00-9218-ee2120d3ecd9",
- "version": 4,
- "weekStart": ""
-}
\ No newline at end of file
+ "version": 5
+}
diff --git a/devenv/dev-dashboards/panel-table/table_tests.json b/devenv/dev-dashboards/panel-table/table_tests.json
index b8ca436e110..a8d0a0d5253 100644
--- a/devenv/dev-dashboards/panel-table/table_tests.json
+++ b/devenv/dev-dashboards/panel-table/table_tests.json
@@ -431,7 +431,11 @@
],
"refresh": false,
"schemaVersion": 16,
- "tags": ["gdev", "panel-tests"],
+ "tags": [
+ "gdev",
+ "panel-tests",
+ "table"
+ ],
"templating": {
"list": []
},
@@ -445,5 +449,5 @@
"timezone": "browser",
"title": "Panel Tests - Table",
"uid": "pttable",
- "version": 2
+ "version": 3
}
diff --git a/devenv/dev-dashboards/panel-table/table_tests_new.json b/devenv/dev-dashboards/panel-table/table_tests_new.json
index 69b50b9b23e..e928e9fc578 100644
--- a/devenv/dev-dashboards/panel-table/table_tests_new.json
+++ b/devenv/dev-dashboards/panel-table/table_tests_new.json
@@ -995,7 +995,8 @@
"schemaVersion": 41,
"tags": [
"gdev",
- "panel-tests"
+ "panel-tests",
+ "table"
],
"templating": {
"list": []
diff --git a/docs/sources/administration/grafana-advisor/_index.md b/docs/sources/administration/grafana-advisor/_index.md
index cd9b812d59e..28caf9b1953 100644
--- a/docs/sources/administration/grafana-advisor/_index.md
+++ b/docs/sources/administration/grafana-advisor/_index.md
@@ -90,6 +90,12 @@ This collapsible section provides more details about which checks have been perf
Click the cogwheel in this section to access Grafana Advisor settings, where you can enable or disable checks according to your preferences.
{{< /admonition >}}
+### Enable LLM suggestions
+
+If the [Grafana LLM app](https://grafana.com/grafana/plugins/grafana-llm-app/) is installed, the Advisor can use it to generate suggestions for issues. Enable the LLM app and click the magic (✨) button to generate a suggestion for an issue.
+
+
+
## Address issues
To resolve issues flagged by Grafana Advisor and maintain system reliability, follow the best practices below. Regularly check the Advisor to keep your Grafana instance secure and up to date.
diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md
index 484210ab244..1c5a5fa7272 100644
--- a/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md
+++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-for-app-plugins/index.md
@@ -72,6 +72,7 @@ The following list contains app plugins that have fine-grained RBAC support.
| [Performance Testing (K6)](https://grafana.com/docs/grafana-cloud/testing/k6/) | `k6-app` | [Configure RBAC for K6](https://grafana.com/docs/grafana-cloud/testing/k6/projects-and-users/configure-rbac/) |
| [Private data source connect (PDC)](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/) | `grafana-pdc-app` | n/a |
| [Service Level Objective (SLO)](https://grafana.com/docs/grafana-cloud/alerting-and-irm/slo/) | `grafana-slo-app` | [Configure RBAC for SLO](https://grafana.com/docs/grafana-cloud/alerting-and-irm/slo/set-up/rbac/) |
+| [Cloud Provider](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/) | `grafana-csp-app` | [Cloud Provider Observability role-based access control](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/rbac/) |
### Revoke fine-grained access from app plugins
diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
index 4d4ec4b3200..a01783fb921 100644
--- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
+++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
@@ -62,13 +62,13 @@ For more details on contact points, including how to test them and enable notifi
| Key | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Title | The issue title. Supports templating. Max length is 255 characters. |
+| Summary | The issue title. Supports templating. Max length is 255 characters. |
| Description | The description of the issue. Depending on version of the API, it can be a text, Markdown, or JSON (v3 API only). Maximum size of the field is 32kb. **Note:** JSON is not limited by the client, and if it exceeds the size, the API is likely to reject the request. |
| Labels | Custom labels can be added to organize and filter issues created in Jira. Supports templating, allowing dynamic label generation based on alert data. |
| Priority | The priority level of the issue (e.g., `Low`, `Medium`, `High`, `Critical`). Ensure that the priority value matches the available options for your Jira instance. You can customize priority levels in Jira [here](https://support.atlassian.com/jira-cloud-administration/docs/configure-priorities/). |
| Resolve Transition | The transition name to move the issue to a resolved state when an alert is resolved. Ensure that the value matches a valid transition available in your Jira workflow for the specified issue type. If this field is empty, the issue will not be transitioned to Done. |
| Reopen Transition | The transition name to move the issue back to an open state when an alert reoccurs. Ensure that the value matches a valid transition available in your Jira workflow for the specified issue type. If this field is empty, the issue will not be reopened. |
| Reopen Duration | The time duration (in minutes) to control whether to reopen an issue that was closed within this duration or create a new one. If not specified, the most recent issue that matches the deduplication key will be updated and reopened (if reopen transition is specified). |
-| Ignored Resolution | Specify a resolution status that should be ignored when searching for existing issues. For example, issues with this resolution will not be reopened or updated by subsequent alerts. |
+| "Won't fix" Transition | Specify a resolution status that should be ignored when searching for existing issues. For example, issues with this resolution will not be reopened or updated by subsequent alerts. |
| Deduplication Key Field | Custom field to store the deduplication key. Must be a text field. If not specified, the deduplication key is added to labels in the format of `ALERT(hash sum)`. See [Jira documentation](https://support.atlassian.com/jira-cloud-administration/docs/create-a-custom-field/) for how to create custom fields. |
| Fields | Allows to configure custom fields of Jira issue. The field name should be of the format like `customfield_10001`. |
diff --git a/docs/sources/dashboards/build-dashboards/_index.md b/docs/sources/dashboards/build-dashboards/_index.md
index 4c228c3458c..4978be9dd35 100644
--- a/docs/sources/dashboards/build-dashboards/_index.md
+++ b/docs/sources/dashboards/build-dashboards/_index.md
@@ -28,7 +28,3 @@ refs:
This section includes the following topics:
{{< section >}}
-
-## Dynamic dashboards
-
-You can create more interactive and dynamic dashboards by adding and using [variables](ref:variables). Instead of hard-coding things like server, application, and sensor names in your metric queries, you can use variables in their place. Read more about variables [here](ref:variables).
diff --git a/docs/sources/dashboards/variables/variable-syntax/index.md b/docs/sources/dashboards/variables/variable-syntax/index.md
index fd876b86847..7d0fbc81993 100644
--- a/docs/sources/dashboards/variables/variable-syntax/index.md
+++ b/docs/sources/dashboards/variables/variable-syntax/index.md
@@ -94,6 +94,16 @@ String to interpolate: '${servers:glob}'
Interpolation result: '{test1,test2}'
```
+### Join
+
+Formats multi-valued variables with a custom delimiter. If no delimiter argument is supplied, they will be combined with `,`.
+
+```bash
+servers = ["test1", "test2"]
+String to interpolate: '${servers:join:&}'
+Interpolation result: "test1&test2"
+```
+
### JSON
Formats variables with multiple values as a comma-separated string.
@@ -134,6 +144,24 @@ String to interpolate: '${servers:pipe}'
Interpolation result: 'test1.|test2'
```
+### Query parameters
+
+Formats single- and multi-valued variables into their query parameter representation. Example: `var-foo=value1&var-foo=value2`
+
+```bash
+servers = ["test1", "test2"]
+String to interpolate: '${servers:queryparam}'
+Interpolation result: "var-servers=test1&var-servers=test2"
+```
+
+Use the `customqueryparam` formatter to customize how the query parameters are formatted. It accepts two optional arguments to specify the parameter name, and a value prefix.
+
+```bash
+servers = ["test1", "test2"]
+String to interpolate: '${servers:customqueryparam:v-servers:x-}'
+Interpolation result: "v-servers=x-test1&v-servers=x-test2"
+```
+
### Raw
Doesn't apply any data source-specific formatting to the variable.
@@ -194,13 +222,3 @@ servers = ["test1", "test2"]
String to interpolate: '${servers:text}'
Interpolation result: "test1 + test2"
```
-
-### Query parameters
-
-Formats single- and multi-valued variables into their query parameter representation. Example: `var-foo=value1&var-foo=value2`
-
-```bash
-servers = ["test1", "test2"]
-String to interpolate: '${servers:queryparam}'
-Interpolation result: "var-servers=test1&var-servers=test2"
-```
diff --git a/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md b/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
index 5df10ff1eae..0d289af1380 100644
--- a/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
+++ b/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
@@ -160,26 +160,22 @@ securityContext:
## Use Grafana Assume Role
{{< admonition type="note" >}}
-Grafana Assume Role is currently in [private preview](https://grafana.com/docs/release-life-cycle/) for Grafana Cloud.
+Grafana Assume Role is only available in Grafana Cloud.
-It's currently only available for Amazon CloudWatch.
-
-To gain early access to this feature, contact Customer Support and ask for the `awsDatasourcesTempCredentials` feature toggle to be enabled on your account.
+It's currently only available for Amazon CloudWatch and Athena.
{{< /admonition >}}
The Grafana Assume Role authentication provider lets you authenticate with AWS without having to create and maintain long term AWS users or rotate their access and secret keys. Instead, you can create an IAM role that has permissions to access CloudWatch and a trust relationship with Grafana's AWS account. Grafana's AWS account then makes an STS request to AWS to create temporary credentials to access your AWS data. It makes this STS request by passing along an `externalID` that's unique per Cloud account, to ensure that Grafana Cloud users can only access their own AWS data. For more information, refer to the [AWS documentation on external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html).
To use the Grafana Assume Role:
-1. Grafana Cloud customers need to open a support ticket to enable the feature `awsDatasourcesTempCredentials`.
- This feature is enabled by default in open source Grafana and Grafana Enterprise.
-2. Once the feature is enabled, create a new CloudWatch data source (or update an existing one) and select **Grafana Assume Role** as an authentication provider.
-3. In the AWS Console, create a new IAM role, and under **Trusted entity type**, select **Another AWS account** as the trusted Entity.
-4. Enter Grafana's account id (displayed in the instructions box on the **Settings** tab of the CloudWatch data source configuration) and check the **Require external ID** box.
-5. Enter the external ID specified in the instructions box on the **Settings** tab of the CloudWatch data source configuration in Grafana. This external ID will be unique to your Grafana instance.
-6. Attach any required permissions you would like Grafana to be able to access on your behalf (for example, CloudWatch Logs and CloudWatch Metrics policies).
-7. Give the role a name and description, and click **Create role**.
-8. Copy the ARN of the role you just created and paste it into the **Assume Role ARN** field on the **Settings** tab of CloudWatch data source configuration in Grafana.
+1. Create a new CloudWatch data source (or update an existing one) and select **Grafana Assume Role** as an authentication provider.
+2. In the AWS Console, create a new IAM role, and under **Trusted entity type**, select **Another AWS account** as the trusted Entity.
+3. Enter the Grafana account id (displayed in the instructions box on the **Settings** tab of the CloudWatch data source configuration) and check the **Require external ID** box.
+4. Enter the external ID specified in the instructions box on the **Settings** tab of the CloudWatch data source configuration in Grafana. This external ID will be unique to your Grafana instance.
+5. Attach any required permissions you would like Grafana to be able to access on your behalf (for example, CloudWatch Logs and CloudWatch Metrics policies).
+6. Give the role a name and description, and click **Create role**.
+7. Copy the ARN of the role you just created and paste it into the **Assume Role ARN** field on the **Settings** tab of CloudWatch data source configuration in Grafana.
Sample Trust Relationship for an IAM role:
diff --git a/docs/sources/datasources/loki/_index.md b/docs/sources/datasources/loki/_index.md
index 523be2c9fbc..4176a2771e7 100644
--- a/docs/sources/datasources/loki/_index.md
+++ b/docs/sources/datasources/loki/_index.md
@@ -62,7 +62,7 @@ The following guides will help you get started with Loki:
This data source supports these versions of Loki:
-- v2.8+
+- v2.9+
## Adding a data source
diff --git a/docs/sources/observability-as-code/schema-v2/_index.md b/docs/sources/observability-as-code/schema-v2/_index.md
index 61de6337b15..9dafaf936bf 100644
--- a/docs/sources/observability-as-code/schema-v2/_index.md
+++ b/docs/sources/observability-as-code/schema-v2/_index.md
@@ -20,7 +20,7 @@ weight: 200
{{< admonition type="caution" >}}
-Dashboard JSON schema v2 is an experimental feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. Enable the `dashboardNewLayouts` feature toggle in Grafana to use this feature.
+Dashboard JSON schema v2 is an [experimental](https://grafana.com/docs/release-life-cycle/) feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
**Do not enable this feature in production environments as it may result in the irreversible loss of data.**
@@ -32,7 +32,8 @@ Observability as Code works with all versions of the JSON model, and it's fully
## Before you begin
-Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle, `dashboardNewLayouts`.
+Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle.
+To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
It also requires the new dashboards API feature toggle, `kubernetesDashboards`, to be enabled as well.
For more information on how dashboards behave depending on your feature flag configuration, refer to [Notes and limitations](#notes-and-limitations).
@@ -217,18 +218,18 @@ Upon saving, they’ll be updated to the new schema where you can take advantage
### Dashboard behavior with disabled feature flags
-If you disable the `dashboardNewLayouts` or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
+If you disable the Dynamic dashboards or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
-#### Disable `dashboardNewLayouts`
+#### Disable Dynamic dashboards
-If `dashboardNewLayouts` feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
+If the Dynamic dashboards feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
- Dashboards built on the new schema through the UI - View only
- Dashboards built on Schema v1 - View and edit
- Dashboards built on the new schema by way of Terraform or the CLI - View and edit
- Provisioned dashboards built on the new schema - View and edit, but the edit experience will be the old experience
-#### Disable `dashboardNewLayouts` and `kubernetesDashboards`
+#### Disable Dynamic dashboards and `kubernetesDashboards`
You’ll be unable to view or edit dashboards created or updated in the new schema.
diff --git a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md
index 529c517f2f9..7782acad459 100644
--- a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md
+++ b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md
@@ -635,7 +635,7 @@ This transformation goes in two steps. First you specify one or multiple fields
| 2020-07-07 10:31:22 | **_server 3_** | 55 | OK |
| 2020-07-07 09:30:57 | **_server 3_** | 62 | Rebooting |
-All rows with the same value of Server ID are grouped together.
+All rows with the same value of Server ID are grouped together. Optionally, you can add a count of how may values fall in the selected group.
After choosing which field you want to group your data by, you can add various calculations on the other fields, and apply the calculation to each group of rows. For instance, we could want to calculate the average CPU temperature for each of those servers. So we can add the _mean_ calculation applied on the CPU Temperature field to get the following:
@@ -645,6 +645,14 @@ After choosing which field you want to group your data by, you can add various c
| server 2 | 88.6 |
| server 3 | 59.6 |
+If you had added the count stat to the group by, there would be an extra column showing that the count of each server from above was 3.
+
+| Server ID | CPU Temperature (mean) | Server ID (count) |
+| --------- | ---------------------- | ----------------- |
+| server 1 | 82 | 3 |
+| server 2 | 88.6 | 3 |
+| server 3 | 59.6 | 3 |
+
And we can add more than one calculation. For instance:
- For field Time, we can calculate the _Last_ value, to know when the last data point was received for each server
diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md
index 50b0e485bdd..1ce20139b48 100644
--- a/docs/sources/setup-grafana/configure-grafana/_index.md
+++ b/docs/sources/setup-grafana/configure-grafana/_index.md
@@ -1547,7 +1547,7 @@ Use spaces to separate multiple modes, for example, `console file`.
#### `level`
-Options are `debug`, `info`, `warn`, `error`, and `critical`. Default is `info`.
+Options are `debug`, `info`, `warn`, `error`. `critical` is an alias for `error`. Default is `info`.
#### `filters`
@@ -1576,7 +1576,7 @@ Only applicable when `console` is used in `[log]` mode.
#### `level`
-Options are `debug`, `info`, `warn`, `error`, and `critical`. Default is inherited from `[log]` level.
+See [`[log] level`](#level) for values. Default is inherited from `[log]` level.
#### `format`
@@ -1590,7 +1590,7 @@ Only applicable when `file` used in `[log]` mode.
#### `level`
-Options are `debug`, `info`, `warn`, `error`, and `critical`. Default is inherited from `[log]` level.
+See [`[log] level`](#level) for values. Default is inherited from `[log]` level.
#### `format`
@@ -1625,7 +1625,7 @@ Only applicable when `syslog` used in `[log]` mode.
#### `level`
-Options are `debug`, `info`, `warn`, `error`, and `critical`. Default is inherited from `[log]` level.
+See [`[log] level`](#level) for values. Default is inherited from `[log]` level.
#### `format`
@@ -2838,22 +2838,14 @@ For example:
```ini
[time_picker]
-quick_ranges = [
- {
- "display": "Last 5 minutes",
- "from": "now-5m",
- "to": "now",
- },
- {
- "display": "Yesterday",
- "from": "now-1d/d",
- },
- {
- "display": "Today so far",
- "from": "now/d",
- "to": "now",
- }
-]
+quick_ranges = """[
+{"from":"now-6s","to":"now","display":"Last 6 seconds"},
+{"from":"now-10m","to":"now","display":"Last 10 minutes"},
+{"from":"now-25h","to":"now","display":"Last 24 hours"},
+{"from":"now/w","to":"now/w","display":"This week"},
+{"from":"now-1w/w","to":"now-1w/w","display":"Last week"},
+{"from":"now-10d","to":"now","display":"Last 10 days"}
+]"""
```
### `[expressions]`
@@ -2866,7 +2858,7 @@ Set this to `false` to disable expressions and hide them in the Grafana UI. Defa
Set the maximum number of cells that can be passed to a SQL expression. Default is `100000`.
-#### `sql_expression_cell_output_limit`
+#### `sql_expression_output_cell_limit`
Set the maximum number of cells that can be returned from a SQL expression. Default is `100000`.
diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
index c20e71dab3d..303cd8e4839 100644
--- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
+++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
@@ -38,6 +38,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
| `pluginsDetailsRightPanel` | Enables right panel for the plugins details page | Yes |
| `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes |
| `logsExploreTableVisualisation` | A table visualisation for logs in Explore | Yes |
+| `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers | Yes |
| `transformationsRedesign` | Enables the transformations redesign | Yes |
| `awsAsyncQueryCaching` | Enable caching for async queries for Redshift and Athena. Requires that the datasource has caching and async query support enabled | Yes |
| `dashgpt` | Enable AI powered features in dashboards | Yes |
@@ -72,7 +73,6 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
| `pluginsSriChecks` | Enables SRI checks for plugin assets | |
| `azureMonitorDisableLogLimit` | Disables the log limit restriction for Azure Monitor when true. The limit is enabled by default. | |
| `preinstallAutoUpdate` | Enables automatic updates for pre-installed plugins | Yes |
-| `jaegerBackendMigration` | Enables querying the Jaeger data source without the proxy | Yes |
| `alertingUIOptimizeReducer` | Enables removing the reducer from the alerting UI when creating a new alert rule and using instant query | Yes |
| `azureMonitorEnableUserAuth` | Enables user auth for Azure Monitor datasource only | Yes |
| `alertingNotificationsStepMode` | Enables simplified step mode in the notifications section | Yes |
@@ -82,7 +82,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
| `alertingMigrationUI` | Enables the alerting migration UI, to migrate data source-managed rules to Grafana-managed rules | Yes |
| `alertingImportYAMLUI` | Enables a UI feature for importing rules from a Prometheus file to Grafana-managed rules | Yes |
| `unifiedNavbars` | Enables unified navbars | |
-| `tabularNumbers` | Use fixed-width numbers globally in the UI | Yes |
+| `tabularNumbers` | Use fixed-width numbers globally in the UI | |
## Public preview feature toggles
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md
index d2d8180482f..f381c212abb 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md
@@ -236,9 +236,11 @@ With our Grafana and Apache containers running, you can now connect to http://lo
If the user is deleted from Grafana, the user will be not be able to login and resync until after the `sync_ttl` has expired.
{{< /admonition >}}
-### Team Sync (Enterprise only)
+### Team Sync
-> Only available in Grafana Enterprise v6.3+
+{{< admonition type="note" >}}
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
+{{< /admonition >}}
With Team Sync, it's possible to set up synchronization between teams in your authentication provider and Grafana. You can send Grafana values as part of an HTTP header and have Grafana map them to your team structure. This allows you to put users into specific teams automatically.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md
index 0b6cbec6a95..5d5b5489061 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md
@@ -239,10 +239,6 @@ Ensure that you have followed the steps in [Create the Microsoft Entra ID applic
## Configure Azure AD authentication client using the Grafana UI
-{{< admonition type="note" >}}
-Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle.
-{{< /admonition >}}
-
As a Grafana Admin, you can configure your Azure AD/Entra ID OAuth client from within Grafana using the Grafana UI. To do this, navigate to the **Administration > Authentication > Azure AD** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values.
After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations.
@@ -255,10 +251,6 @@ If you run Grafana in high availability mode, configuration changes may not get
## Configure Azure AD authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "azuread_sso_settings" {
provider_name = "azuread"
@@ -426,7 +418,11 @@ This setting is ignored if multiple auth providers are configured to use auto lo
auto_login = true
```
-### Team Sync (Enterprise only)
+### Team Sync
+
+{{< admonition type="note" >}}
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
+{{< /admonition >}}
With Team Sync you can map your Entra ID groups to teams in Grafana so that your users will automatically be added to
the correct teams.
@@ -556,11 +552,13 @@ The following table outlines the various Azure AD/Entra ID configuration options
| `allowed_groups` | No | Yes | List of comma- or space-separated groups. The user should be a member of at least one group to log in. If you configure `allowed_groups`, you must also configure Azure AD/Entra ID to include the `groups` claim following [Configure group membership claims on the Azure Portal](#configure-group-membership-claims-on-the-azure-portal). | |
| `allowed_organizations` | No | Yes | List of comma- or space-separated Azure tenant identifiers. The user should be a member of at least one tenant to log in. | |
| `allowed_domains` | No | Yes | List of comma- or space-separated domains. The user should belong to at least one domain to log in. | |
-| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
-| `tls_client_cert` | No | No | The path to the certificate. | |
-| `tls_client_key` | No | No | The path to the key. | |
-| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
-| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
-| `use_refresh_token` | No | Yes | Enables the use of refresh tokens and checks for access token expiration. When enabled, Grafana automatically adds the `offline_access` scope to the list of scopes. | `true` |
-| `force_use_graph_api` | No | Yes | Set to `true` to always fetch groups from the Microsoft Graph API instead of the `id_token`. If a user belongs to more than 200 groups, the Microsoft Graph API will be used to retrieve the groups regardless of this setting. | `false` |
-| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
+| `domain_hint` | No | Yes | The realm of the user in a federated directory. This skips the email-based discovery process that the user goes through on the Azure AD/Entra ID sign-in page, for a slightly more streamlined user experience. More info [here](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#send-the-sign-in-request). | |
+
+| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
+| `tls_client_cert` | No | No | The path to the certificate. | |
+| `tls_client_key` | No | No | The path to the key. | |
+| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
+| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `true` |
+| `use_refresh_token` | No | Yes | Enables the use of refresh tokens and checks for access token expiration. When enabled, Grafana automatically adds the `offline_access` scope to the list of scopes. | `true` |
+| `force_use_graph_api` | No | Yes | Set to `true` to always fetch groups from the Microsoft Graph API instead of the `id_token`. If a user belongs to more than 200 groups, the Microsoft Graph API will be used to retrieve the groups regardless of this setting. | `false` |
+| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md
index 17305e59a3f..7b8d312b4af 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md
@@ -49,10 +49,6 @@ If Users use the same email address in Azure AD that they use with other authent
## Configure generic OAuth authentication client using the Grafana UI
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
-{{< /admonition >}}
-
As a Grafana Admin, you can configure Generic OAuth client from within Grafana using the Generic OAuth UI. To do this, navigate to **Administration > Authentication > Generic OAuth** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations.
@@ -67,10 +63,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure generic OAuth authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "generic_sso_settings" {
provider_name = "generic_oauth"
@@ -134,7 +126,7 @@ To integrate your OAuth2 provider with Grafana using our Generic OAuth authentic
### Configure login
-Grafana can resolve a user's login from the OAuth2 ID token or user information retrieved from the OAuth2 UserInfo endpoint.
+Grafana can resolve a user's login from the OAuth2 ID token, user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 access token.
Grafana looks at these sources in the order listed until it finds a login.
If no login is found, then the user's login is set to user's email address.
@@ -146,10 +138,12 @@ Refer to the following table for information on what to configure based on how y
| Another field of the OAuth2 ID token. | Set `login_attribute_path` configuration option. |
| `login` or `username` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `login_attribute_path` configuration option. |
+| `login` or `username` field of the OAuth2 access token. | N/A |
+| Another field of the OAuth2 access token. | Set `login_attribute_path` configuration option. |
### Configure display name
-Grafana can resolve a user's display name from the OAuth2 ID token or user information retrieved from the OAuth2 UserInfo endpoint.
+Grafana can resolve a user's display name from the OAuth2 ID token, user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 access token.
Grafana looks at these sources in the order listed until it finds a display name.
If no display name is found, then user's login is displayed instead.
@@ -161,10 +155,12 @@ Refer to the following table for information on what you need to configure depen
| Another field of the OAuth2 ID token. | Set `name_attribute_path` configuration option. |
| `name` or `display_name` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `name_attribute_path` configuration option. |
+| `name` or `display_name` field of the OAuth2 access token. | N/A |
+| Another field of the OAuth2 access token. | Set `name_attribute_path` configuration option. |
### Configure email address
-Grafana can resolve the user's email address from the OAuth2 ID token, the user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 `/emails` endpoint.
+Grafana can resolve the user's email address from the OAuth2 ID token, the user information retrieved from the OAuth2 UserInfo endpoint, the OAuth2 access token, or the OAuth2 `/emails` endpoint.
Grafana looks at these sources in the order listed until an email address is found.
If no email is found, then the email address of the user is set to an empty string.
@@ -177,6 +173,10 @@ Refer to the following table for information on what to configure based on how t
| `upn` field of the OAuth2 ID token. | N/A |
| `email` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `email_attribute_path` configuration option. |
+| `email` field of the OAuth2 access token. | N/A |
+| `attributes` map of the OAuth2 access token. | Set `email_attribute_name` configuration option. By default, Grafana searches for email under `email:primary` key. |
+| `upn` field of the OAuth2 access token. | N/A |
+| Another field of the OAuth2 access token. | Set `email_attribute_path` configuration option. |
| Email address marked as primary from the `/emails` endpoint of the OAuth2 provider (obtained by appending `/emails` to the URL configured with `api_url`) | N/A |
### Configure a refresh token
@@ -199,6 +199,7 @@ The `accessTokenExpirationCheck` feature toggle has been removed in Grafana v10.
Unless `skip_org_role_sync` option is enabled, the user's role will be set to the role retrieved from the auth provider upon user login.
The user's role is retrieved using a [JMESPath](http://jmespath.org/examples.html) expression from the `role_attribute_path` configuration option.
+Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no role is found, the expression will be evaluated using the OAuth2 access token.
To map the server administrator role, use the `allow_assign_grafana_admin` configuration option.
Refer to [configuration options](#configuration-options) for more information.
@@ -319,13 +320,14 @@ org_mapping = org_foo:org_foo:Viewer org_bar:org_bar:Editor *:org_baz:Editor
## Configure team synchronization
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can link your OAuth2 groups to teams within Grafana. This will automatically assign users to the appropriate teams.
Teams for each user are synchronized when the user logs in.
Generic OAuth groups can be referenced by group ID, such as `8bab1c86-8fba-33e5-2089-1d1c80ec267d` or `myteam`.
+Group information can be extracted from the OAuth2 ID token, user information from the UserInfo endpoint, or the OAuth2 access token.
For information on configuring OAuth2 groups with Grafana using the `groups_attribute_path` configuration option, refer to [configuration options](#configuration-options).
To learn more about Team Sync, refer to [Configure team sync](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-team-sync/).
@@ -359,46 +361,46 @@ The following table outlines the various Generic OAuth configuration options. Yo
If the configuration option requires a JMESPath expression that includes a colon, enclose the entire expression in quotes to prevent parsing errors. For example `role_attribute_path: "role:view"`
{{< /admonition >}}
-| Setting | Required | Supported on Cloud | Description | Default |
-| ---------------------------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
-| `enabled` | No | Yes | Enables Generic OAuth authentication. | `false` |
-| `name` | No | Yes | Name that refers to the Generic OAuth authentication from the Grafana user interface. | `OAuth` |
-| `icon` | No | Yes | Icon used for the Generic OAuth authentication in the Grafana user interface. | `signin` |
-| `client_id` | Yes | Yes | Client ID provided by your OAuth2 app. | |
-| `client_secret` | Yes | Yes | Client secret provided by your OAuth2 app. | |
-| `auth_url` | Yes | Yes | Authorization endpoint of your OAuth2 provider. | |
-| `token_url` | Yes | Yes | Endpoint used to obtain the OAuth2 access token. | |
-| `api_url` | Yes | Yes | Endpoint used to obtain user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | |
-| `auth_style` | No | Yes | Name of the [OAuth2 AuthStyle](https://pkg.go.dev/golang.org/x/oauth2#AuthStyle) to be used when ID token is requested from OAuth2 provider. It determines how `client_id` and `client_secret` are sent to Oauth2 provider. Available values are `AutoDetect`, `InParams` and `InHeader`. | `AutoDetect` |
-| `scopes` | No | Yes | List of comma- or space-separated OAuth2 scopes. | `user:email` |
-| `empty_scopes` | No | Yes | Set to `true` to use an empty scope during authentication. | `false` |
-| `allow_sign_up` | No | Yes | Controls Grafana user creation through the Generic OAuth login. Only existing Grafana users can log in with Generic OAuth if set to `false`. | `true` |
-| `auto_login` | No | Yes | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
-| `id_token_attribute_name` | No | Yes | The name of the key used to extract the ID token from the returned OAuth2 token. | `id_token` |
-| `login_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user login lookup from the user ID token. For more information on how user login is retrieved, refer to [Configure login](#configure-login). | |
-| `name_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user name lookup from the user ID token. This name will be used as the user's display name. For more information on how user display name is retrieved, refer to [Configure display name](#configure-display-name). | |
-| `email_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user email lookup from the user information. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | |
-| `email_attribute_name` | No | Yes | Name of the key to use for user email lookup within the `attributes` map of OAuth2 ID token. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | `email:primary` |
-| `role_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | |
-| `role_attribute_strict` | No | Yes | Set to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
-| `skip_org_role_sync` | No | Yes | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
-| `org_attribute_path` | No | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
-| `org_mapping` | No | No | List of comma- or space-separated `::` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
-| `allow_assign_grafana_admin` | No | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
-| `groups_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user group lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no groups are found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a string array of groups. | |
-| `allowed_groups` | No | Yes | List of comma- or space-separated groups. The user should be a member of at least one group to log in. If you configure `allowed_groups`, you must also configure `groups_attribute_path`. | |
-| `allowed_organizations` | No | Yes | List of comma- or space-separated organizations. The user should be a member of at least one organization to log in. | |
-| `allowed_domains` | No | Yes | List of comma- or space-separated domains. The user should belong to at least one domain to log in. | |
-| `team_ids` | No | Yes | String list of team IDs. If set, the user must be a member of one of the given teams to log in. If you configure `team_ids`, you must also configure `teams_url` and `team_ids_attribute_path`. | |
-| `team_ids_attribute_path` | No | Yes | The [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana team ID lookup within the results returned by the `teams_url` endpoint. | |
-| `teams_url` | No | Yes | The URL used to query for team IDs. If not set, the default value is `/teams`. If you configure `teams_url`, you must also configure `team_ids_attribute_path`. | |
-| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
-| `tls_client_cert` | No | No | The path to the certificate. | |
-| `tls_client_key` | No | No | The path to the key. | |
-| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
-| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `false` |
-| `use_refresh_token` | No | Yes | Set to `true` to use refresh token and check access token expiration. | `false` |
-| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
+| Setting | Required | Supported on Cloud | Description | Default |
+| ---------------------------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
+| `enabled` | No | Yes | Enables Generic OAuth authentication. | `false` |
+| `name` | No | Yes | Name that refers to the Generic OAuth authentication from the Grafana user interface. | `OAuth` |
+| `icon` | No | Yes | Icon used for the Generic OAuth authentication in the Grafana user interface. | `signin` |
+| `client_id` | Yes | Yes | Client ID provided by your OAuth2 app. | |
+| `client_secret` | Yes | Yes | Client secret provided by your OAuth2 app. | |
+| `auth_url` | Yes | Yes | Authorization endpoint of your OAuth2 provider. | |
+| `token_url` | Yes | Yes | Endpoint used to obtain the OAuth2 access token. | |
+| `api_url` | Yes | Yes | Endpoint used to obtain user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | |
+| `auth_style` | No | Yes | Name of the [OAuth2 AuthStyle](https://pkg.go.dev/golang.org/x/oauth2#AuthStyle) to be used when ID token is requested from OAuth2 provider. It determines how `client_id` and `client_secret` are sent to Oauth2 provider. Available values are `AutoDetect`, `InParams` and `InHeader`. | `AutoDetect` |
+| `scopes` | No | Yes | List of comma- or space-separated OAuth2 scopes. | `user:email` |
+| `empty_scopes` | No | Yes | Set to `true` to use an empty scope during authentication. | `false` |
+| `allow_sign_up` | No | Yes | Controls Grafana user creation through the Generic OAuth login. Only existing Grafana users can log in with Generic OAuth if set to `false`. | `true` |
+| `auto_login` | No | Yes | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
+| `id_token_attribute_name` | No | Yes | The name of the key used to extract the ID token from the returned OAuth2 token. | `id_token` |
+| `login_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user login lookup from the user ID token. For more information on how user login is retrieved, refer to [Configure login](#configure-login). | |
+| `name_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user name lookup from the user ID token. This name will be used as the user's display name. For more information on how user display name is retrieved, refer to [Configure display name](#configure-display-name). | |
+| `email_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user email lookup from the user information. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | |
+| `email_attribute_name` | No | Yes | Name of the key to use for user email lookup within the `attributes` map of OAuth2 ID token. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | `email:primary` |
+| `role_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no role is found, the expression will be evaluated using the OAuth2 access token. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | |
+| `role_attribute_strict` | No | Yes | Set to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
+| `skip_org_role_sync` | No | Yes | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
+| `org_attribute_path` | No | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no value is returned, the expression will be evaluated using the OAuth2 access token. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
+| `org_mapping` | No | No | List of comma- or space-separated `::` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
+| `allow_assign_grafana_admin` | No | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
+| `groups_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user group lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no groups are found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no groups are found, the expression will be evaluated using the OAuth2 access token. The result of the evaluation should be a string array of groups. | |
+| `allowed_groups` | No | Yes | List of comma- or space-separated groups. The user should be a member of at least one group to log in. If you configure `allowed_groups`, you must also configure `groups_attribute_path`. | |
+| `allowed_organizations` | No | Yes | List of comma- or space-separated organizations. The user should be a member of at least one organization to log in. | |
+| `allowed_domains` | No | Yes | List of comma- or space-separated domains. The user should belong to at least one domain to log in. | |
+| `team_ids` | No | Yes | String list of team IDs. If set, the user must be a member of one of the given teams to log in. If you configure `team_ids`, you must also configure `teams_url` and `team_ids_attribute_path`. | |
+| `team_ids_attribute_path` | No | Yes | The [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana team ID lookup within the results returned by the `teams_url` endpoint. | |
+| `teams_url` | No | Yes | The URL used to query for team IDs. If not set, the default value is `/teams`. If you configure `teams_url`, you must also configure `team_ids_attribute_path`. | |
+| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
+| `tls_client_cert` | No | No | The path to the certificate. | |
+| `tls_client_key` | No | No | The path to the key. | |
+| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
+| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `false` |
+| `use_refresh_token` | No | Yes | Set to `true` to use refresh token and check access token expiration. | `false` |
+| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
## Examples of setting up Generic OAuth
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md
index 387f23425fb..9546be11af3 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md
@@ -43,10 +43,6 @@ Ensure you know how to create a GitHub OAuth app. Consult GitHub's documentation
## Configure GitHub authentication client using the Grafana UI
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
-{{< /admonition >}}
-
As a Grafana Admin, you can configure GitHub OAuth client from within Grafana using the GitHub UI. To do this, navigate to **Administration > Authentication > GitHub** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -61,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure GitHub authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "github_sso_settings" {
provider_name = "github"
@@ -219,7 +211,7 @@ role_attribute_path = [login=='octocat'][0] && 'GrafanaAdmin' || 'Viewer'
## Configure team synchronization
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and Grafana Cloud.
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can map teams from your GitHub organization to teams within Grafana. This will automatically assign users to the appropriate teams.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md
index 04a39492d50..16c3ba72032 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md
@@ -57,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure GitLab authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "gitlab_sso_settings" {
provider_name = "gitlab"
@@ -241,7 +237,7 @@ use_refresh_token = true
## Configure team synchronization
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can map GitLab groups to teams within Grafana. This will automatically assign users to the appropriate teams.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md
index 0d77243b6ae..8085e222252 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md
@@ -45,10 +45,6 @@ First, you need to create a Google OAuth Client:
## Configure Google authentication client using the Grafana UI
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
-{{< /admonition >}}
-
As a Grafana Admin, you can configure Google OAuth client from within Grafana using the Google UI. To do this, navigate to **Administration > Authentication > Google** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -61,10 +57,6 @@ If you run Grafana in high availability mode, configuration changes may not get
## Configure Google authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "google_sso_settings" {
provider_name = "google"
@@ -167,6 +159,10 @@ auto_login = true
### Configure team synchronization
+{{< admonition type="note" >}}
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
+{{< /admonition >}}
+
With team sync, you can easily add users to teams by utilizing their Google groups. To set up team sync for Google OAuth, refer to the following example.
To set up team sync for Google OAuth:
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md
index 5798ee15540..88adc9d4a2a 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md
@@ -106,10 +106,10 @@ editor
viewer
```
-## Teamsync
+## Team sync
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
[Teamsync](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-team-sync/) is a feature that allows you to map groups from your identity provider to Grafana teams. This is useful if you want to give your users access to specific dashboards or folders based on their group membership.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md
index ff316b4d2f6..3a90f19b371 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md
@@ -101,10 +101,6 @@ If you want to configure the role for all users in the Okta directory, you can a
## Configure Okta authentication client using the Grafana UI
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
-{{< /admonition >}}
-
As a Grafana Admin, you can configure Okta OAuth2 client from within Grafana using the Okta UI. To do this, navigate to **Administration > Authentication > Okta** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -119,10 +115,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure Okta authentication client using the Terraform provider
-{{< admonition type="note" >}}
-Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
-{{< /admonition >}}
-
```terraform
resource "grafana_sso_settings" "okta_sso_settings" {
provider_name = "okta"
@@ -243,10 +235,10 @@ org_attribute_path = groups
org_mapping = ["Group 1:org_foo:Viewer", "Group 2:org_bar:Editor", "*:3:Editor"]
```
-### Configure team synchronization (Enterprise only)
+### Configure team synchronization
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud](../../../../introduction/grafana-cloud).
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can link your Okta groups to teams within Grafana. This will automatically assign users to the appropriate teams.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md
index 06a38944b83..4a846a622e2 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/_index.md
@@ -40,7 +40,7 @@ If you are using Okta or Azure AD as Identity Provider, see the following docume
- [Configure SAML with Okta](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/saml/configure-saml-with-okta/)
{{< admonition type="note" >}}
-The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle. You must also enable the `ssoSettingsApi` flag.
+The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle.
{{< /admonition >}}
All methods offer the same configuration options. However, if you want to keep all of Grafana authentication settings in one place, use the Grafana configuration file or the Terraform provider. If you are a Grafana Cloud user, you do not have access to Grafana configuration file. Instead, configure SAML through the other methods.
diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md
index a7c6bc3fd88..edfedcefb9a 100644
--- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md
@@ -11,6 +11,10 @@ weight: 540
# Configure team sync for SAML
+{{< admonition type="note" >}}
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
+{{< /admonition >}}
+
To use SAML Team sync, set [`assertion_attribute_groups`](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/enterprise-configuration/#assertion_attribute_groups) to the attribute name where you store user groups. Then Grafana will use attribute values extracted from SAML assertion to add user into the groups with the same name configured on the External group sync tab.
{{< admonition type="warning" >}}
diff --git a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md
index 4d9a5dab53c..75729ee8b7d 100644
--- a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md
+++ b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md
@@ -20,7 +20,8 @@ weight: 300
System for Cross-domain Identity Management (SCIM) is an open standard that allows automated user provisioning and management. With SCIM, you can automate the provisioning of users and groups from your identity provider to Grafana.
{{< admonition type="note" >}}
-Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
+Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/) in [public preview](https://grafana.com/docs/release-life-cycle/).
+Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
{{< /admonition >}}
{{< admonition type="note" >}}
diff --git a/docs/sources/setup-grafana/configure-security/configure-team-sync.md b/docs/sources/setup-grafana/configure-security/configure-team-sync.md
index c7c16c0f924..f99de6a6189 100644
--- a/docs/sources/setup-grafana/configure-security/configure-team-sync.md
+++ b/docs/sources/setup-grafana/configure-security/configure-team-sync.md
@@ -16,7 +16,9 @@ weight: 1000
Team sync lets you set up synchronization between your auth providers teams and teams in Grafana. This enables LDAP, OAuth, or SAML users who are members of certain teams or groups to automatically be added or removed as members of certain teams in Grafana.
-> **Note:** Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
+{{< admonition type="note" >}}
+Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
+{{< /admonition >}}
Grafana keeps track of all synchronized users in teams, and you can see which users have been synchronized in the team members list, see `LDAP` label in screenshot.
This mechanism allows Grafana to remove an existing synchronized user from a team when its group membership changes. This mechanism also enables you to manually add a user as member of a team, and it will not be removed when the user signs in. This gives you flexibility to combine LDAP group memberships and Grafana team memberships.
@@ -27,14 +29,14 @@ This mechanism allows Grafana to remove an existing synchronized user from a tea
## Supported providers
-- [Auth Proxy](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/auth-proxy/#team-sync-enterprise-only)
-- [Azure AD](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/azuread/#team-sync-enterprise-only)
+- [Auth Proxy](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/auth-proxy/#team-sync)
+- [Azure AD](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/azuread/#team-sync)
- [Generic OAuth integration](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/generic-oauth/#configure-team-synchronization)
- [GitHub OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/github/#configure-team-synchronization)
- [GitLab OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/gitlab/#configure-team-synchronization)
- [Google OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/google/#configure-team-synchronization)
- [LDAP](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/enhanced-ldap/)
-- [Okta](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/okta/#configure-team-synchronization-enterprise-only)
+- [Okta](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/okta/#configure-team-synchronization)
- [SAML](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/saml/)
## Synchronize a Grafana team with an external group
diff --git a/docs/sources/shared/visualizations/datalink-options-2.md b/docs/sources/shared/visualizations/datalink-options-2.md
index c34cb13a228..37cc660b23d 100644
--- a/docs/sources/shared/visualizations/datalink-options-2.md
+++ b/docs/sources/shared/visualizations/datalink-options-2.md
@@ -26,6 +26,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.
To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
+| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.
Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |
diff --git a/docs/sources/shared/visualizations/datalink-options-3.md b/docs/sources/shared/visualizations/datalink-options-3.md
index bc68c9c45fb..f99d6c9a065 100644
--- a/docs/sources/shared/visualizations/datalink-options-3.md
+++ b/docs/sources/shared/visualizations/datalink-options-3.md
@@ -28,6 +28,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.
To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
+| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.