Merge remote-tracking branch 'origin/main' into alerting/improved-filters

alerting/improved-filters
Gilles De Mey 2 months ago
commit 987fbcbcfc
No known key found for this signature in database
  1. 6
      .betterer.eslint.config.js
  2. 233
      .betterer.results
  3. 2
      .citools/src/cog/go.mod
  4. 4
      .citools/src/cog/go.sum
  5. 4
      .github/CODEOWNERS
  6. 95
      .github/actions/changelog/index.js
  7. 92
      .github/actions/changelog/semver.js
  8. 47
      .github/workflows/backport-trigger.yml
  9. 88
      .github/workflows/backport-workflow.yml
  10. 50
      .github/workflows/backport.yml
  11. 52
      .github/workflows/changelog.yml
  12. 2
      .github/workflows/codeql-analysis.yml
  13. 20
      .github/workflows/dashboards-issue-add-label.yml
  14. 5
      .github/workflows/i18n-crowdin-create-tasks.yml
  15. 13
      .github/workflows/pr-codeql-analysis-python.yml
  16. 34
      .github/workflows/release-pr.yml
  17. 2
      .gitignore
  18. 1
      .ignore
  19. 155
      apps/advisor/README.md
  20. 16
      apps/advisor/go.mod
  21. 4
      apps/advisor/go.sum
  22. 12
      apps/advisor/pkg/app/checkregistry/checkregistry.go
  23. 2
      apps/advisor/pkg/app/checks/authchecks/check.go
  24. 48
      apps/advisor/pkg/app/checks/configchecks/check.go
  25. 73
      apps/advisor/pkg/app/checks/configchecks/security_config_step.go
  26. 33
      apps/advisor/pkg/app/checks/configchecks/security_config_step_test.go
  27. 2
      apps/advisor/pkg/app/checks/datasourcecheck/check.go
  28. 185
      apps/advisor/pkg/app/checks/plugincheck/check.go
  29. 91
      apps/advisor/pkg/app/checks/plugincheck/check_test.go
  30. 76
      apps/advisor/pkg/app/checks/plugincheck/deprecation_step.go
  31. 94
      apps/advisor/pkg/app/checks/plugincheck/unsigned_step.go
  32. 76
      apps/advisor/pkg/app/checks/plugincheck/update_step.go
  33. 7
      apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer.go
  34. 2
      apps/alerting/notifications/Makefile
  35. 40
      apps/alerting/notifications/go.mod
  36. 94
      apps/alerting/notifications/go.sum
  37. 12
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/constants.go
  38. 5
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_metadata_gen.go
  39. 8
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/receiver_spec_gen.go
  40. 5
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/routingtree_metadata_gen.go
  41. 1
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/routingtree_spec_gen.go
  42. 5
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/templategroup_metadata_gen.go
  43. 5
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_metadata_gen.go
  44. 4
      apps/alerting/notifications/pkg/apis/alerting/v0alpha1/timeinterval_spec_gen.go
  45. 27
      apps/alerting/notifications/pkg/apis/alerting_manifest.go
  46. 2
      apps/dashboard/Makefile
  47. 22
      apps/dashboard/go.mod
  48. 54
      apps/dashboard/go.sum
  49. 15
      apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
  50. 12
      apps/dashboard/pkg/apis/dashboard/v0alpha1/constants.go
  51. 5
      apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_metadata_gen.go
  52. 1
      apps/dashboard/pkg/apis/dashboard/v0alpha1/zz_generated.openapi_violation_exceptions.list
  53. 12
      apps/dashboard/pkg/apis/dashboard/v1beta1/constants.go
  54. 5
      apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_metadata_gen.go
  55. 1
      apps/dashboard/pkg/apis/dashboard/v1beta1/zz_generated.openapi_violation_exceptions.list
  56. 12
      apps/dashboard/pkg/apis/dashboard/v2alpha1/constants.go
  57. 5
      apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_metadata_gen.go
  58. 15
      apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue
  59. 200
      apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go
  60. 120
      apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go
  61. 4
      apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi_violation_exceptions.list
  62. 28
      apps/dashboard/pkg/apis/dashboard_manifest.go
  63. 2
      apps/folder/Makefile
  64. 16
      apps/folder/go.mod
  65. 40
      apps/folder/go.sum
  66. 12
      apps/folder/pkg/apis/folder/v1beta1/constants.go
  67. 5
      apps/folder/pkg/apis/folder/v1beta1/folder_metadata_gen.go
  68. 4
      apps/folder/pkg/apis/folder/v1beta1/register.go
  69. 1
      apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi_violation_exceptions.list
  70. 24
      apps/folder/pkg/apis/folder_manifest.go
  71. 2
      apps/iam/Makefile
  72. 14
      apps/iam/go.mod
  73. 38
      apps/iam/go.sum
  74. 12
      apps/iam/pkg/apis/iam/v0alpha1/constants.go
  75. 5
      apps/iam/pkg/apis/iam/v0alpha1/corerole_metadata_gen.go
  76. 4
      apps/iam/pkg/apis/iam/v0alpha1/corerole_spec_gen.go
  77. 5
      apps/iam/pkg/apis/iam/v0alpha1/globalrole_metadata_gen.go
  78. 4
      apps/iam/pkg/apis/iam/v0alpha1/globalrole_spec_gen.go
  79. 5
      apps/iam/pkg/apis/iam/v0alpha1/globalrolebinding_metadata_gen.go
  80. 3
      apps/iam/pkg/apis/iam/v0alpha1/globalrolebinding_spec_gen.go
  81. 5
      apps/iam/pkg/apis/iam/v0alpha1/resourcepermission_metadata_gen.go
  82. 7
      apps/iam/pkg/apis/iam/v0alpha1/resourcepermission_spec_gen.go
  83. 5
      apps/iam/pkg/apis/iam/v0alpha1/role_metadata_gen.go
  84. 4
      apps/iam/pkg/apis/iam/v0alpha1/role_spec_gen.go
  85. 5
      apps/iam/pkg/apis/iam/v0alpha1/rolebinding_metadata_gen.go
  86. 3
      apps/iam/pkg/apis/iam/v0alpha1/rolebinding_spec_gen.go
  87. 29
      apps/iam/pkg/apis/iam_manifest.go
  88. 20
      apps/investigations/go.mod
  89. 5
      apps/investigations/go.sum
  90. 30
      apps/playlist/Makefile
  91. 22
      apps/playlist/go.mod
  92. 44
      apps/playlist/go.sum
  93. 12
      apps/playlist/pkg/apis/playlist/v0alpha1/constants.go
  94. 5
      apps/playlist/pkg/apis/playlist/v0alpha1/playlist_metadata_gen.go
  95. 63
      apps/playlist/pkg/apis/playlist/v0alpha1/playlist_object_gen.go
  96. 4
      apps/playlist/pkg/apis/playlist/v0alpha1/playlist_spec_gen.go
  97. 5
      apps/playlist/pkg/apis/playlist/v0alpha1/zz_openapi_gen.go
  98. 27
      apps/playlist/pkg/apis/playlist_manifest.go
  99. 17
      conf/defaults.ini
  100. 17
      conf/sample.ini
  101. Some files were not shown because too many files have changed in this diff Show More

@ -10,6 +10,7 @@ const testingLibraryPlugin = require('eslint-plugin-testing-library');
const grafanaConfig = require('@grafana/eslint-config/flat'); const grafanaConfig = require('@grafana/eslint-config/flat');
const grafanaPlugin = require('@grafana/eslint-plugin'); const grafanaPlugin = require('@grafana/eslint-plugin');
const grafanaI18nPlugin = require('@grafana/i18n/eslint-plugin');
// Include the Grafana config and remove the rules, // Include the Grafana config and remove the rules,
// as we just want to pull in all of the necessary configuration but not run the rules // as we just want to pull in all of the necessary configuration but not run the rules
@ -65,6 +66,7 @@ module.exports = [
'no-barrel-files': barrelPlugin, 'no-barrel-files': barrelPlugin,
'@grafana': grafanaPlugin, '@grafana': grafanaPlugin,
'testing-library': testingLibraryPlugin, 'testing-library': testingLibraryPlugin,
'@grafana/i18n': grafanaI18nPlugin,
}, },
linterOptions: { linterOptions: {
// This reports unused disable directives that we can clean up but // This reports unused disable directives that we can clean up but
@ -122,11 +124,11 @@ module.exports = [
'error', 'error',
{ {
selector: 'Identifier[name=localStorage]', selector: 'Identifier[name=localStorage]',
message: 'Direct usage of localStorage is not allowed. Use `Store` from @grafana/data instead.', message: 'Direct usage of localStorage is not allowed. import store from @grafana/data instead',
}, },
{ {
selector: 'MemberExpression[object.name=localStorage]', selector: 'MemberExpression[object.name=localStorage]',
message: 'Direct usage of localStorage is not allowed. Use `Store` from @grafana/data instead.', message: 'Direct usage of localStorage is not allowed. import store from @grafana/data instead',
}, },
{ {
selector: selector:

@ -12,15 +12,15 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"e2e/old-arch/utils/support/localStorage.ts:5381": [ "e2e/old-arch/utils/support/localStorage.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"e2e/old-arch/utils/support/types.ts:5381": [ "e2e/old-arch/utils/support/types.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"e2e/utils/support/localStorage.ts:5381": [ "e2e/utils/support/localStorage.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"e2e/utils/support/types.ts:5381": [ "e2e/utils/support/types.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
@ -369,12 +369,12 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"packages/grafana-data/src/utils/store.ts:5381": [ "packages/grafana-data/src/utils/store.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"]
], ],
"packages/grafana-data/src/utils/url.ts:5381": [ "packages/grafana-data/src/utils/url.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "0"],
@ -421,12 +421,12 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"packages/grafana-prometheus/src/components/metrics-browser/useMetricsLabelsValues.ts:5381": [ "packages/grafana-prometheus/src/components/metrics-browser/useMetricsLabelsValues.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"]
], ],
"packages/grafana-prometheus/src/datasource.ts:5381": [ "packages/grafana-prometheus/src/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "0"],
@ -479,7 +479,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"packages/grafana-runtime/src/config.ts:5381": [ "packages/grafana-runtime/src/config.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"], [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.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"], [0, 0, 0, "Do not use any type assertions.", "3"],
@ -530,18 +530,18 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"packages/grafana-runtime/src/utils/userStorage.tsx:5381": [ "packages/grafana-runtime/src/utils/userStorage.tsx:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "6"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "6"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "7"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "7"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "8"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "8"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "9"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "9"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "10"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "10"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "11"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "11"]
], ],
"packages/grafana-schema/src/veneer/common.types.ts:5381": [ "packages/grafana-schema/src/veneer/common.types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -557,9 +557,13 @@ exports[`better eslint`] = {
], ],
"packages/grafana-sql/src/components/configuration/ConnectionLimits.tsx:5381": [ "packages/grafana-sql/src/components/configuration/ConnectionLimits.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.", "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.", "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"] "packages/grafana-sql/src/components/configuration/MaxLifetimeField.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"]
],
"packages/grafana-sql/src/components/configuration/MaxOpenConnectionsField.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"]
], ],
"packages/grafana-sql/src/components/configuration/TLSSecretsConfig.tsx:5381": [ "packages/grafana-sql/src/components/configuration/TLSSecretsConfig.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.", "0"],
@ -644,9 +648,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "4"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"] [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
], ],
"packages/grafana-ui/src/components/Select/ValueContainer.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-ui/src/components/Select/resetSelectStyles.ts:5381": [ "packages/grafana-ui/src/components/Select/resetSelectStyles.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [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.", "1"],
@ -840,7 +841,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"packages/grafana-ui/src/utils/logger.ts:5381": [ "packages/grafana-ui/src/utils/logger.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"]
], ],
"packages/grafana-ui/src/utils/useAsyncDependency.ts:5381": [ "packages/grafana-ui/src/utils/useAsyncDependency.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -959,9 +960,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"public/app/core/reducers/appNotification.ts:5381": [ "public/app/core/reducers/appNotification.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"]
], ],
"public/app/core/services/ResponseQueue.ts:5381": [ "public/app/core/services/ResponseQueue.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -987,6 +988,9 @@ exports[`better eslint`] = {
"public/app/core/specs/backend_srv.test.ts:5381": [ "public/app/core/specs/backend_srv.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"public/app/core/store.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`store\`)", "0"]
],
"public/app/core/time_series2.ts:5381": [ "public/app/core/time_series2.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [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.", "1"],
@ -1185,11 +1189,6 @@ exports[`better eslint`] = {
"public/app/features/alerting/unified/components/create-folder/CreateNewFolder.tsx:5381": [ "public/app/features/alerting/unified/components/create-folder/CreateNewFolder.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.", "0"]
], ],
"public/app/features/alerting/unified/components/import-to-gma/ImportFromDSRules.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"]
],
"public/app/features/alerting/unified/components/import-to-gma/NamespaceAndGroupFilter.tsx:5381": [ "public/app/features/alerting/unified/components/import-to-gma/NamespaceAndGroupFilter.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.", "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.", "1"]
@ -1319,14 +1318,14 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx:5381": [ "public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "6"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "6"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "7"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "7"]
], ],
"public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/contactPoint/ContactPointSelector.tsx:5381": [ "public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/contactPoint/ContactPointSelector.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.", "0"]
@ -1416,12 +1415,12 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"public/app/features/alerting/unified/rule-editor/formDefaults.ts:5381": [ "public/app/features/alerting/unified/rule-editor/formDefaults.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"]
], ],
"public/app/features/alerting/unified/rule-list/FilterViewStatus.tsx:5381": [ "public/app/features/alerting/unified/rule-list/FilterViewStatus.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, "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"]
@ -1484,8 +1483,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"public/app/features/browse-dashboards/api/useRecentlyDeletedStateManager.ts:5381": [ "public/app/features/browse-dashboards/api/useRecentlyDeletedStateManager.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"public/app/features/browse-dashboards/components/BrowseActions/MoveModal.tsx:5381": [ "public/app/features/browse-dashboards/components/BrowseActions/MoveModal.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.", "0"]
@ -1641,15 +1640,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "5"], [0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"] [0, 0, 0, "Unexpected any. Specify a different type.", "6"]
], ],
"public/app/features/dashboard-scene/saving/provisioned/SaveProvisionedDashboardForm.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/scene/PanelMenuBehavior.tsx:5381": [ "public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
@ -1759,8 +1749,7 @@ 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.", "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.", "0"]
], ],
"public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.tsx:5381": [ "public/app/features/dashboard-scene/settings/variables/components/GroupByVariableForm.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.", "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"]
], ],
"public/app/features/dashboard-scene/settings/variables/components/QueryVariableForm.tsx:5381": [ "public/app/features/dashboard-scene/settings/variables/components/QueryVariableForm.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.", "0"]
@ -2507,12 +2496,12 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"public/app/features/logs/utils.ts:5381": [ "public/app/features/logs/utils.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"],
[0, 0, 0, "Do not use any type assertions.", "6"] [0, 0, 0, "Do not use any type assertions.", "6"]
], ],
"public/app/features/manage-dashboards/DashboardImportPage.tsx:5381": [ "public/app/features/manage-dashboards/DashboardImportPage.tsx:5381": [
@ -2739,26 +2728,12 @@ exports[`better eslint`] = {
[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.", "2"], [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.", "2"],
[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.", "3"] [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.", "3"]
], ],
"public/app/features/provisioning/Wizard/BootstrapStep.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, "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"]
],
"public/app/features/provisioning/Wizard/ConnectStep.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"]
],
"public/app/features/provisioning/Wizard/FinishStep.tsx:5381": [ "public/app/features/provisioning/Wizard/FinishStep.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.", "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.", "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.", "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.", "3"]
], ],
"public/app/features/provisioning/Wizard/SynchronizeStep.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/provisioning/types.ts:5381": [ "public/app/features/provisioning/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
@ -2806,10 +2781,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"] [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
], ],
"public/app/features/scopes/selector/ScopesSelectorService.ts:5381": [ "public/app/features/scopes/selector/ScopesSelectorService.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"]
], ],
"public/app/features/search/page/components/columns.tsx:5381": [ "public/app/features/search/page/components/columns.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
@ -2826,31 +2801,31 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"public/app/features/search/state/SearchStateManager.ts:5381": [ "public/app/features/search/state/SearchStateManager.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "6"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "6"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "7"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "7"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "8"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "8"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "9"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "9"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "10"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "10"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "11"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "11"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "12"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "12"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "13"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "13"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "14"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "14"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "15"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "15"],
[0, 0, 0, "Do not use any type assertions.", "16"] [0, 0, 0, "Do not use any type assertions.", "16"]
], ],
"public/app/features/search/types.ts:5381": [ "public/app/features/search/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"public/app/features/search/utils.ts:5381": [ "public/app/features/search/utils.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"] [0, 0, 0, "Do not use any type assertions.", "3"]
], ],
"public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx:5381": [ "public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx:5381": [
@ -3760,21 +3735,21 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
], ],
"public/app/plugins/datasource/loki/LogContextProvider.ts:5381": [ "public/app/plugins/datasource/loki/LogContextProvider.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"public/app/plugins/datasource/loki/components/LokiContextUi.tsx:5381": [ "public/app/plugins/datasource/loki/components/LokiContextUi.tsx:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "2"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "2"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "3"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "3"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "4"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "4"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "5"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "5"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "6"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "6"]
], ],
"public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx:5381": [ "public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"public/app/plugins/datasource/loki/configuration/ConfigEditor.tsx:5381": [ "public/app/plugins/datasource/loki/configuration/ConfigEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"] [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -3801,12 +3776,12 @@ exports[`better eslint`] = {
[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, "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/plugins/datasource/loki/querybuilder/state.ts:5381": [ "public/app/plugins/datasource/loki/querybuilder/state.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"public/app/plugins/datasource/loki/shardQuerySplitting.ts:5381": [ "public/app/plugins/datasource/loki/shardQuerySplitting.ts:5381": [
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "0"], [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "0"],
[0, 0, 0, "Direct usage of localStorage is not allowed. Use \`Store\` from @grafana/data instead.", "1"] [0, 0, 0, "Direct usage of localStorage is not allowed. import store from @grafana/data instead", "1"]
], ],
"public/app/plugins/datasource/loki/types.ts:5381": [ "public/app/plugins/datasource/loki/types.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`LokiQueryDirection\`)", "0"], [0, 0, 0, "Do not re-export imported variable (\`LokiQueryDirection\`)", "0"],

@ -17,7 +17,7 @@ require (
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d // indirect github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d // indirect
github.com/grafana/cog v0.0.28 // indirect github.com/grafana/cog v0.0.34 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huandu/xstrings v1.5.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect

@ -27,8 +27,8 @@ 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d h1:hrXbGJ5jgp6yNITzs5o+zXq0V5yT3siNJ+uM8LGwWKk= github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d h1:hrXbGJ5jgp6yNITzs5o+zXq0V5yT3siNJ+uM8LGwWKk=
github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s= github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
github.com/grafana/cog v0.0.28 h1:0+FNuxyfNWm1OBZPPjgBIno3nzR4gOpSxsVe34hdN7g= github.com/grafana/cog v0.0.34 h1:tXtjIB0A0Y6jeZ5iAQBJIAz5vkAJsV0iEFfX94PH/+Q=
github.com/grafana/cog v0.0.28/go.mod h1:wZWsTLV7uX0jCbGpqvjawQ7JbaDVT9oW+PQhHwqanHc= github.com/grafana/cog v0.0.34/go.mod h1:UDstzYqMdgIROmbfkHL8fB9XWQO2lnf5z+4W/eJo4Dc=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=

@ -259,7 +259,6 @@
/devenv/docker/blocks/etcd @grafana/grafana-app-platform-squad /devenv/docker/blocks/etcd @grafana/grafana-app-platform-squad
/devenv/docker/blocks/grafana/ @grafana/grafana-as-code /devenv/docker/blocks/grafana/ @grafana/grafana-as-code
/devenv/docker/blocks/graphite/ @grafana/partner-datasources /devenv/docker/blocks/graphite/ @grafana/partner-datasources
/devenv/docker/blocks/graphite09/ @grafana/partner-datasources
/devenv/docker/blocks/graphite1/ @grafana/partner-datasources /devenv/docker/blocks/graphite1/ @grafana/partner-datasources
/devenv/docker/blocks/influxdb/ @grafana/partner-datasources /devenv/docker/blocks/influxdb/ @grafana/partner-datasources
/devenv/docker/blocks/influxdb1/ @grafana/partner-datasources /devenv/docker/blocks/influxdb1/ @grafana/partner-datasources
@ -774,7 +773,8 @@ embed.go @grafana/grafana-as-code
/.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad /.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/backend-code-checks.yml @grafana/grafana-backend-group /.github/workflows/backend-code-checks.yml @grafana/grafana-backend-group
/.github/workflows/backend-unit-tests.yml @grafana/grafana-backend-group /.github/workflows/backend-unit-tests.yml @grafana/grafana-backend-group
/.github/workflows/backport.yml @grafana/grafana-developer-enablement-squad /.github/workflows/backport-trigger.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/backport-workflow.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/bump-version.yml @grafana/grafana-developer-enablement-squad /.github/workflows/bump-version.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/release-pr.yml @grafana/grafana-developer-enablement-squad /.github/workflows/release-pr.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/release-comms.yml @grafana/grafana-developer-enablement-squad /.github/workflows/release-comms.yml @grafana/grafana-developer-enablement-squad

@ -1,6 +1,7 @@
import { appendFileSync, writeFileSync } from 'fs'; import {appendFileSync, writeFileSync} from 'fs';
import { exec as execCallback } from 'node:child_process'; import {exec as execCallback} from 'node:child_process';
import { promisify } from 'node:util'; import {promisify} from 'node:util';
import {findPreviousVersion, semverParse} from "./semver.js";
// //
// Github Action core utils: logging (notice + debug log levels), must escape // Github Action core utils: logging (notice + debug log levels), must escape
@ -9,35 +10,6 @@ import { promisify } from 'node:util';
const escapeData = (s) => s.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A'); const escapeData = (s) => s.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
const LOG = (msg) => console.log(`::notice::${escapeData(msg)}`); const LOG = (msg) => console.log(`::notice::${escapeData(msg)}`);
//
// Semver utils: parse, compare, sort etc (using official regexp)
// https://regex101.com/r/Ly7O1x/3/
//
const semverRegExp =
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
const semverParse = (tag) => {
const m = tag.match(semverRegExp);
if (!m) {
return;
}
const [_, major, minor, patch, prerelease] = m;
return [+major, +minor, +patch, prerelease, tag];
};
// semverCompare takes two parsed semver tags and comparest them more or less
// according to the semver specs
const semverCompare = (a, b) => {
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) {
return a[i] < b[i] ? 1 : -1;
}
}
if (a[3] !== b[3]) {
return a[3] < b[3] ? 1 : -1;
}
return 0;
};
// Using `git tag -l` output find the tag (version) that goes semantically // Using `git tag -l` output find the tag (version) that goes semantically
// right before the given version. This might not work correctly with some // right before the given version. This might not work correctly with some
@ -45,29 +17,32 @@ const semverCompare = (a, b) => {
// into this action explicitly to avoid this step. // into this action explicitly to avoid this step.
const getPreviousVersion = async (version) => { const getPreviousVersion = async (version) => {
const exec = promisify(execCallback); const exec = promisify(execCallback);
const { stdout } = await exec('git tag -l'); const {stdout} = await exec('git for-each-ref --sort=-creatordate --format \'%(refname:short)\' refs/tags');
const prev = stdout
const parsedTags = stdout
.split('\n') .split('\n')
.map(semverParse) .map(semverParse)
.filter((tag) => tag) .filter(Boolean);
.sort(semverCompare)
.find((tag) => semverCompare(tag, semverParse(version)) > 0); const parsedVersion = semverParse(version);
const prev = findPreviousVersion(parsedTags, parsedVersion);
if (!prev) { if (!prev) {
throw `Could not find previous git tag for ${version}`; throw `Could not find previous git tag for ${version}`;
} }
return prev[4]; return prev[5];
}; };
// A helper for Github GraphQL API endpoint // A helper for Github GraphQL API endpoint
const graphql = async (ghtoken, query, variables) => { const graphql = async (ghtoken, query, variables) => {
const { env } = process; const {env} = process;
const results = await fetch('https://api.github.com/graphql', { const results = await fetch('https://api.github.com/graphql', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${ghtoken}`, Authorization: `Bearer ${ghtoken}`,
}, },
body: JSON.stringify({ query, variables }), body: JSON.stringify({query, variables}),
}); });
const res = await results.json(); const res = await results.json();
@ -100,7 +75,7 @@ const getCommitishDate = async (name, owner, target) => {
} }
} }
`, `,
{ name, owner, target } {name, owner, target}
); );
return result.repository.object.committedDate; return result.repository.object.committedDate;
}; };
@ -160,7 +135,7 @@ const getHistory = async (name, owner, from, to) => {
let cursor; let cursor;
let nodes = []; let nodes = [];
for (;;) { for (; ;) {
const result = await graphql(ghtoken, query, { const result = await graphql(ghtoken, query, {
name, name,
owner, owner,
@ -170,7 +145,7 @@ const getHistory = async (name, owner, from, to) => {
}); });
LOG(`GraphQL: ${JSON.stringify(result)}`); LOG(`GraphQL: ${JSON.stringify(result)}`);
nodes = [...nodes, ...result.repository.ref.compare.commits.nodes]; nodes = [...nodes, ...result.repository.ref.compare.commits.nodes];
const { hasNextPage, endCursor } = result.repository.ref.compare.commits.pageInfo; const {hasNextPage, endCursor} = result.repository.ref.compare.commits.pageInfo;
if (!hasNextPage) { if (!hasNextPage) {
break; break;
} }
@ -186,7 +161,7 @@ const getHistory = async (name, owner, from, to) => {
// PR grouping relies on Github labels only, not on the PR contents. // PR grouping relies on Github labels only, not on the PR contents.
const getChangeLogItems = async (name, owner, from, to) => { const getChangeLogItems = async (name, owner, from, to) => {
// check if a node contains a certain label // check if a node contains a certain label
const hasLabel = ({ labels }, label) => labels.nodes.some(({ name }) => name === label); const hasLabel = ({labels}, label) => labels.nodes.some(({name}) => name === label);
// get all the PRs between the two "commitish" items // get all the PRs between the two "commitish" items
const history = await getHistory(name, owner, from, to); const history = await getHistory(name, owner, from, to);
@ -197,17 +172,17 @@ const getChangeLogItems = async (name, owner, from, to) => {
return []; return [];
} }
const item = changes[0]; const item = changes[0];
const { number, url, labels } = item; const {number, url, labels} = item;
const title = item.title.replace(/^\[[^\]]+\]:?\s*/, ''); const title = item.title.replace(/^\[[^\]]+\]:?\s*/, '');
// for changelog PRs try to find a suitable category. // for changelog PRs try to find a suitable category.
// Note that we can not detect "deprecation notices" like that // Note that we can not detect "deprecation notices" like that
// as there is no suitable label yet. // as there is no suitable label yet.
const isBug = /fix/i.test(title) || hasLabel({ labels }, 'type/bug'); const isBug = /fix/i.test(title) || hasLabel({labels}, 'type/bug');
const isBreaking = hasLabel({ labels }, 'breaking change'); const isBreaking = hasLabel({labels}, 'breaking change');
const isPlugin = const isPlugin =
hasLabel({ labels }, 'area/grafana/ui') || hasLabel({labels}, 'area/grafana/ui') ||
hasLabel({ labels }, 'area/grafana/toolkit') || hasLabel({labels}, 'area/grafana/toolkit') ||
hasLabel({ labels }, 'area/grafana/runtime'); hasLabel({labels}, 'area/grafana/runtime');
const author = item.commits.nodes[0].commit.author.user?.login; const author = item.commits.nodes[0].commit.author.user?.login;
return { return {
repo: name, repo: name,
@ -227,7 +202,7 @@ const getChangeLogItems = async (name, owner, from, to) => {
// ====================================================== // ======================================================
LOG(`Changelog action started`); LOG(`Changelog action started`);
console.log(process.argv);
const ghtoken = process.env.GITHUB_TOKEN || process.env.INPUT_GITHUB_TOKEN; const ghtoken = process.env.GITHUB_TOKEN || process.env.INPUT_GITHUB_TOKEN;
if (!ghtoken) { if (!ghtoken) {
throw 'GITHUB_TOKEN is not set and "github_token" input is empty'; throw 'GITHUB_TOKEN is not set and "github_token" input is empty';
@ -286,15 +261,15 @@ const markdown = (changelog) => {
: `### ${title} : `### ${title}
${items ${items
.map( .map(
(item) => (item) =>
`- ${item.title.replace(/^([^:]*:)/gm, '**$1**')} ${ `- ${item.title.replace(/^([^:]*:)/gm, '**$1**')} ${
item.repo === 'grafana-enterprise' item.repo === 'grafana-enterprise'
? '(Enterprise)' ? '(Enterprise)'
: `${pullRequestLink(item.number)}${item.author ? ', ' + userLink(item.author) : ''}` : `${pullRequestLink(item.number)}${item.author ? ', ' + userLink(item.author) : ''}`
}` }`
) )
.join('\n')} .join('\n')}
`; `;
// Render all present sections for the given changelog // Render all present sections for the given changelog

@ -0,0 +1,92 @@
//
// Semver utils: parse, compare, sort etc (using official regexp)
// https://regex101.com/r/Ly7O1x/3/
//
const semverRegExp =
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
export function semverParse(tag) {
const m = tag.match(semverRegExp);
if (!m) {
return;
}
const [_, major, minor, patch, prerelease, build] = m;
return [+major, +minor, +patch, prerelease, build, tag];
};
// semverCompare takes two parsed semver tags and comparest them more or less
// according to the semver specs
export function semverCompare(a, b) {
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) {
return a[i] < b[i] ? 1 : -1;
}
}
if (a[3] !== b[3]) {
return a[3] < b[3] ? 1 : -1;
}
return 0;
};
// Finds the highest version that is lower than the target version.
//
// This function relies on the following invariant: versions are sorted by the release date.
// It will produce wrong result if invariant doesn't hold.
export const findPreviousVersion = (versionByDate, target) => {
let prev = null;
for (let i = 0; i < versionByDate.length; i++) {
const version = versionByDate[i];
// version is greater than the target
if (semverCompare(target, version) > 0) {
continue;
}
// we came across the target version, all versions seen previously have greater release date.
if (semverCompare(target, version) === 0 && target[4] === version[4]) {
prev = null;
continue;
}
if (prev == null) {
prev = version;
continue;
}
if (semverCompare(prev, version) > 0) {
prev = version;
}
}
return prev;
};
const versionsByDate = [
"v10.4.19", "v12.0.1", "v11.6.2", "v11.5.5", "v11.4.5", "v11.3.7", "v11.2.10", "v12.0.0+security-01", "v11.2.9+security-01", "v11.3.6+security-01",
"v11.6.1+security-01", "v11.4.4+security-01", "v11.5.4+security-01", "v10.4.18+security-01", "v12.0.0", "v11.6.1",
"v11.5.4", "v11.4.4", "v11.3.6", "v11.2.9", "v10.4.18", "v11.6.0+security-01", "v11.5.3+security-01", "v11.4.3+security-01",
"v11.3.5+security-01", "v11.2.8+security-01", "v10.4.17+security-01", "v11.2.8", "v11.6.0", "v11.5.2", "v11.4.2",
"v11.3.4", "v11.2.7", "v11.1.12", "v11.0.11", "v10.4.16", "v11.5.1", "v11.5.0", "v11.3.3", "v11.1.11", "v11.2.6",
"v11.0.10", "v10.4.15", "v11.4.1", "v11.4.0", "v11.3.2", "v11.2.5", "v11.1.10", "v11.0.9", "v10.4.14", "v11.3.1",
"v11.2.4", "v11.1.9", "v11.0.8", "v10.4.13", "v11.0.2", "v10.4.6", "v10.3.8", "v10.2.9", "v11.1.0", "v11.0.1",
"v10.4.5", "v10.3.7", "v10.2.8", "v9.5.20", "v10.4.4", "v9.5.19", "v10.1.10", "v10.2.7", "v10.3.6", "v10.4.3",
"v11.0.0", "v10.4.2", "v11.0.0-preview", "v10.1.9", "v10.0.13", "v9.2.0", "v9.1.8",
].map(semverParse);
function test(version, expected) {
const v1 = semverParse(version);
const prev = findPreviousVersion(versionsByDate, v1);
const failureMessage = `FAIILED. Expected ${expected}, but was ${prev[5]}`;
console.log(`Test ${version}, ${prev[5] === expected ? 'PASSED' : failureMessage}`);
}
test("v11.5.4+security-01", "v11.5.4");
test("v11.5.4", "v11.5.3+security-01");
test("v12.0.0", "v11.6.1");
test("v12.0.0+security-01", "v12.0.0");
test("v11.0.0", "v11.0.0-preview");

@ -0,0 +1,47 @@
# We need secrets to backport, but they're not available for actions ran by forks.
# So this workflow is used as a 'trigger', which the backport-workflow.yml will with
# via workflow_run
name: Backport (trigger)
on:
pull_request:
types:
- closed
- labeled
permissions: {}
jobs:
trigger:
# Only run this job if the PR has been merged and has a label containing "backport v"
if: |
github.repository == 'grafana/grafana' &&
github.event.pull_request.merged == true &&
contains(join(github.event.pull_request.labels.*.name, ','), 'backport v')
runs-on: ubuntu-latest
steps:
# TODO: save this as job summary instead?
- name: Trigger
run: |
echo "Triggering workflow"
echo "See https://github.com/${{ github.repository }}/actions/workflows/workflow_run.yml for progress"
# Create a JSON artifact with details of this PR to pass to the backport workflow.
# The { action: 'labelled', label: 'backport-1.23.x' } can only be determined from this event payload,
# and is needed to do a backport after a PR has been merged
#
# Important that we don't run *anything* from the PR which could modify the backport_data.json file
- name: Create action data
run: |
jq '{
action: .action,
label: .label.name,
pr_number: .number,
}' "$GITHUB_EVENT_PATH" > /tmp/pr_info.json
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pr_info
path: /tmp/pr_info.json
retention-days: 1

@ -0,0 +1,88 @@
# Runs the actual backport, after being triggered by the backport-trigger.yml workflow.
name: Backport (workflow)
run-name: "Backport for ${{ github.event.workflow_run.head_branch }} #${{ github.event.workflow_run.run_number }}"
on:
workflow_run: # zizmor: ignore[dangerous-triggers] backport-trigger.yml does not run any user code
workflows: ["Backport (trigger)"]
types:
- completed
permissions: {}
jobs:
backport:
# Only run this job if the triggering workflow was not skipped (and on grafana repo)
if: github.repository == 'grafana/grafana' && github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
permissions:
id-token: write
actions: read
steps:
- name: Get vault secrets
id: secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
export_env: false
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ fromJSON(steps.secrets.outputs.secrets).APP_PEM }}
- name: Download PR info artifact
uses: actions/download-artifact@v4
id: download-pr-info
with:
github-token: ${{ github.token }}
run-id: ${{ github.event.workflow_run.id }}
name: pr_info
- name: Get PR info
id: pr-info
env:
PR_INFO_FILE: ${{ steps.download-pr-info.outputs.download-path }}/pr_info.json
# jq-magic to convert the JSON object into a list of key=value pairs for $GITHUB_OUTPUT
run:
jq -r 'to_entries[] | select(.value | type != "object") | "\(.key)=\(.value)"' "$PR_INFO_FILE" >> "$GITHUB_OUTPUT"
- name: Print PR info
env:
PR_ACTION: ${{ steps.pr-info.outputs.action }}
PR_LABEL: ${{ steps.pr-info.outputs.label }}
PR_NUMBER: ${{ steps.pr-info.outputs.pr_number }}
run: |
echo "PR action: $PR_ACTION"
echo "PR label: $PR_LABEL"
echo "PR number: $PR_NUMBER"
- name: Checkout Grafana
uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
fetch-depth: 2
fetch-tags: false
token: ${{ steps.generate_token.outputs.token }}
persist-credentials: true
- name: Configure git user
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true
- name: Run backport
uses: grafana/grafana-github-actions-go/backport@dev
with:
token: ${{ steps.generate_token.outputs.token }}
# If triggered by being labelled, only backport that label.
# Otherwise, the action will backport all labels.
pr_label: ${{ steps.pr-info.outputs.action == 'labeled' && steps.pr-info.outputs.label || '' }}
pr_number: ${{ steps.pr-info.outputs.pr_number }}
repo_owner: ${{ github.repository_owner }}
repo_name: ${{ github.event.repository.name }}

@ -1,50 +0,0 @@
name: Backport PR Creator
on:
pull_request:
types:
- closed
- labeled
jobs:
# TODO: This workflow won't work for forks because no secrets are available.
# This should, at the least, post the comment with manual backport instructions.
main:
if: github.repository == 'grafana/grafana'
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Get vault secrets
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: Checkout Grafana
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 2
fetch-tags: false
token: ${{ steps.generate_token.outputs.token }}
persist-credentials: true
- name: Configure git user
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true
- name: Run backport
uses: grafana/grafana-github-actions-go/backport@main
with:
token: ${{ steps.generate_token.outputs.token }}

@ -22,6 +22,10 @@ on:
required: false required: false
default: false default: false
type: boolean type: boolean
work_branch:
required: false
type: string
description: "Use specific branch for changelog"
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@ -45,6 +49,10 @@ on:
required: false required: false
default: false default: false
type: boolean type: boolean
work_branch:
required: false
type: string
description: "Use specific branch for changelog"
permissions: {} permissions: {}
@ -98,7 +106,20 @@ jobs:
git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true git config --local --add --bool push.autoSetupRemote true
- name: "Create branch" - name: "Create branch"
run: git checkout -b "changelog/${RUN_ID}/${VERSION}" run: |
if [[ "$WORK_BRANCH" == '' ]]; then
git switch -c "changelog/${RUN_ID}/${VERSION}"
exit 0
fi
# Checkout the changelog branch if exists, otherwise create a new one
if git show-ref --verify --quiet "refs/remotes/origin/$WORK_BRANCH"; then
git switch --track "origin/$WORK_BRANCH"
else
git switch -c "$WORK_BRANCH"
fi
env:
WORK_BRANCH: ${{ inputs.work_branch }}
- name: "Generate changelog" - name: "Generate changelog"
id: changelog id: changelog
uses: ./.github/actions/changelog uses: ./.github/actions/changelog
@ -145,13 +166,26 @@ jobs:
if: inputs.dry_run != true if: inputs.dry_run != true
run: git push run: git push
- name: "Create changelog PR" - name: "Create changelog PR"
run: > run: |
gh pr create \ if gh pr view &>/dev/null; then
--dry-run="${DRY_RUN}" \ echo "Changelog pr has already been created"
--label "no-backport" \ else
--label "no-changelog" \
-B "${TARGET}" \ gh pr create \
--title "Release: update changelog for ${VERSION}" \ --dry-run="${DRY_RUN}" \
--body "Changelog changes for release ${VERSION}" --label "no-backport" \
--label "no-changelog" \
-B "${TARGET}" \
--title "Release: update changelog for ${TARGET}" \
--body "Changelog changes for release versions:"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Add release version to PR description"
if: inputs.dry_run != true
run: |
gh pr view --json body --jq .body > pr_body.md
echo " - ${VERSION}" >> pr_body.md
gh pr edit --body-file pr_body.md
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

@ -35,7 +35,7 @@ jobs:
# Override automatic language detection by changing the below list # Override automatic language detection by changing the below list
# Supported options are listed here # Supported options are listed here
# https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#changing-the-languages-that-are-analyzed # https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#changing-the-languages-that-are-analyzed
language: ['actions', 'javascript', 'go', 'python'] language: ['actions', 'javascript', 'go']
# Learn more... # Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection

@ -11,7 +11,7 @@ env:
ORGANIZATION: ${{ github.repository_owner }} ORGANIZATION: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }} REPO: ${{ github.event.repository.name }}
TARGET_PROJECT: 202 TARGET_PROJECT: 202
LABEL_IDs: "LA_kwDOAOaWjc8AAAABT38U-A" LABEL_IDS: "LA_kwDOAOaWjc8AAAABT38U-A"
concurrency: concurrency:
group: issue-label-when-in-project-${{ github.event.number }} group: issue-label-when-in-project-${{ github.event.number }}
@ -26,15 +26,15 @@ jobs:
with: with:
# Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault # Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault
repo_secrets: | repo_secrets: |
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id GITHUB_APP_ID=grafana_pr_automation_app:app_id
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem
- name: "Generate token" - name: Generate token
id: generate_token id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with: with:
app_id: ${{ env.GH_APP_ID }} app-id: ${{ env.GITHUB_APP_ID }}
private_key: ${{ env.GH_APP_PEM }} private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Check if issue is in target project - name: Check if issue is in target project
env: env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }} GH_TOKEN: ${{ steps.generate_token.outputs.token }}
@ -43,9 +43,9 @@ jobs:
run: | run: |
# shellcheck disable=SC2016 # we don't want the $s to be expanded # shellcheck disable=SC2016 # we don't want the $s to be expanded
gh api graphql -f query=' gh api graphql -f query='
query($org: String!, $repo: String!) { query($org: String!, $repo: String!, $issueNumber: Int!) {
repository(name: $repo, owner: $org) { repository(name: $repo, owner: $org) {
issue (number: $ISSUE_NUMBER) { issue (number: $issueNumber) {
id id
projectItems(first:20) { projectItems(first:20) {
nodes { nodes {
@ -56,7 +56,7 @@ jobs:
} }
} }
} }
}' -f org="$ORGANIZATION" -f repo="$REPO" > projects_data.json }' -f org="$ORGANIZATION" -f repo="$REPO" -F issueNumber="$ISSUE_NUMBER" > projects_data.json
{ {
echo "IN_TARGET_PROJ=$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json)" echo "IN_TARGET_PROJ=$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json)"

@ -3,8 +3,9 @@ name: Crowdin automatic task management
on: on:
workflow_dispatch: workflow_dispatch:
# once a week on Sunday at midnight # once a week on Sunday at midnight
schedule: # TODO enable once we're ready to create tasks automatically
- cron: "0 0 * * 0" # schedule:
# - cron: "0 0 * * 0"
jobs: jobs:
create-tasks-in-crowdin: create-tasks-in-crowdin:

@ -25,11 +25,24 @@ jobs:
fetch-depth: 2 fetch-depth: 2
persist-credentials: false persist-credentials: false
- name: Check for Python files
id: check-python
run: |
if [ -z "$(find . -name '*.py' -type f)" ]; then
echo "No Python files found, skipping analysis"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "Python files found, proceeding with analysis"
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
if: steps.check-python.outputs.skip != 'true'
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3
with: with:
languages: "python" languages: "python"
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
if: steps.check-python.outputs.skip != 'true'
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v3

@ -32,25 +32,59 @@ on:
required: false required: false
default: false default: false
type: boolean type: boolean
release_date:
required: false
type: string
description: "Release date in format YYYY-MM-DD"
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
jobs: jobs:
capture-date:
runs-on: ubuntu-latest
outputs:
release_date: ${{ steps.set_release_date.outputs.release_date }}
steps:
- name: compute_release_date
run: |
if [ -n "$DATE" ]; then
echo "release_date=$DATE" >> "$GITHUB_ENV"
exit 0
fi
echo "Fetching workflow run creation date..."
created_at=$(gh run view "$GITHUB_RUN_ID" --repo "$GH_REPO" --json createdAt -q .createdAt)
formatted_date=$(date -d "$created_at" +%Y-%m-%d)
echo "release_date=$formatted_date" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
DATE: ${{ inputs.release_date }}
- id: set_release_date
run: echo "release_date=$release_date" >> "$GITHUB_OUTPUT"
push-changelog-to-main: push-changelog-to-main:
needs: capture-date
permissions: permissions:
contents: write contents: write
id-token: write id-token: write
pull-requests: write pull-requests: write
name: Create PR to main to update the changelog name: Create PR to main to update the changelog
uses: ./.github/workflows/changelog.yml uses: ./.github/workflows/changelog.yml
concurrency:
group: grafana-release-pr-update-changelog-main
cancel-in-progress: false
with: with:
previous_version: ${{inputs.previous_version}} previous_version: ${{inputs.previous_version}}
version: ${{ inputs.version }} version: ${{ inputs.version }}
latest: ${{ inputs.latest }} latest: ${{ inputs.latest }}
dry_run: ${{ inputs.dry_run }} dry_run: ${{ inputs.dry_run }}
target: main target: main
work_branch: changelog/update-changelog-${{ needs.capture-date.outputs.release_date }}
create-prs: create-prs:
permissions: permissions:

2
.gitignore vendored

@ -41,8 +41,6 @@ __debug_bin*
# This is the new place of the block, but I leave the previous here for a while # This is the new place of the block, but I leave the previous here for a while
/devenv/docker/blocks/auth/saml-enterprise /devenv/docker/blocks/auth/saml-enterprise
/devenv/docker/blocks/auth/signer /devenv/docker/blocks/auth/signer
/devenv/docker/blocks/spanner_tests
/devenv/docker/blocks/spanner_tests_multi
/devenv/docker/blocks/mt-db /devenv/docker/blocks/mt-db
/tmp /tmp

@ -19,4 +19,3 @@
# This is the new place of the block, but I leave the previous here for a while # This is the new place of the block, but I leave the previous here for a while
!/devenv/docker/blocks/auth/saml-enterprise !/devenv/docker/blocks/auth/saml-enterprise
!/devenv/docker/blocks/auth/signer !/devenv/docker/blocks/auth/signer
!/devenv/docker/blocks/spanner_tests

@ -0,0 +1,155 @@
# Grafana Advisor - Implementing New Checks
This guide explains how to implement new checks in the Grafana Advisor system. The Advisor system allows you to create custom checks that can validate various aspects of your Grafana instance.
## Check Structure
A check in Grafana Advisor consists of two main components:
1. A main check struct that implements the [`checks.Check`](https://github.com/grafana/grafana/blob/269226cb50b970ad9f692f1fdd220e9822e90db8/apps/advisor/pkg/app/checks/ifaces.go#L11-L25) interface
2. One or more step structs that implement the [`checks.Step`](https://github.com/grafana/grafana/blob/269226cb50b970ad9f692f1fdd220e9822e90db8/apps/advisor/pkg/app/checks/ifaces.go#L28-L39) interface
## Implementing a New Check
### 1. Create the Check Package
Create a new package in `pkg/app/checks/` for your check. For example, if you're creating a check for validating configuration fields, you might create `pkg/app/checks/configchecks/`. Add a `check.go` file to the package, there we will implement the check interface. Let's start by implementing the `Check` interface but without any steps yet:
```go
package configchecks
var _ checks.Check = (*check)(nil)
type check struct{}
func New() checks.Check {
return &check{}
}
func (c *check) ID() string {
return "config"
}
func (c *check) Name() string {
return "config setting"
}
func (c *check) Items(ctx context.Context) ([]any, error) {
return nil, nil
}
func (c *check) Item(ctx context.Context, id string) (any, error) {
return nil, nil
}
func (c *check) Init(ctx context.Context) error {
return nil
}
func (c *check) Steps() []checks.Step {
return []checks.Step{}
}
```
### 2. Define Dependencies and Register the Check
In order to be able to implement a check, it will likely need some dependencies in the form of `wire` services. This is the internal dependency injection system used in Grafana and it allows you to access the services you need.
For our example, we will need access to the grafana settings, which are exposed by wire as `*setting.Cfg` (in this case is a pointer to a struct, not an interface but the idea is the same). So let's add it to our check as a parameter for our `New` function:
```go
type check struct {
cfg *setting.Cfg
}
func New(cfg *setting.Cfg) checks.Check {
return &check{
cfg: cfg,
}
}
```
Now, to register our check in the `checkregistry` package, we need to add it to the `ProvideService` function. First, we need to verify that the services we need are available in the `ProvideService` function, and if not, add them. Then, we need to add our check to the `Checks` slice.
```go
func ProvideService(..., cfg *setting.Cfg,
) *Service {
return &Service{
...
cfg: cfg,
}
}
func (s *Service) Checks() []checks.Check {
return []checks.Check{
...
configchecks.New(s.cfg),
}
}
```
### 3. Complete the Check Implementation
Now that we have our check registered, we can implement the rest of the check logic.
#### 3.1. Implement the `Items` and `Item` methods
The `Items` method is used to return a list of items that the check will be run on (e.g. all data sources, all plugins, etc). The `Item` method is used to return a single item by its ID.
These functions can return `any` type, we will convert them to the expected type in the step `Run` method.
In our case, we will implement the `Items` method to return a list of config sections that we want to check. The `Item` method will return a single config section by its name.
```go
func (c *check) Items(ctx context.Context) ([]any, error) {
return []any{"security.secret_key"}, nil
}
func (c *check) Item(ctx context.Context, id string) (any, error) {
return id, nil
}
```
Check other checks for examples of how to implement these methods in more interesting ways.
#### 3.2. Implement the `Init` method
The `Init` method is used to initialize the check. It is called when the check is first created. It should be used to gather any information that is needed to run the check and for the steps to have some shared context.
In our case, we don't need to do anything special so we can just return `nil`.
```go
func (c *check) Init(ctx context.Context) error {
return nil
}
```
One more interesting example is the `plugincheck`, where we gather all the plugin information from GCOM and store it in the check struct.
### 4. Implement Steps
Like the `Check` interface, each `Step` needs to return some information (metadata) about the step, which will be used to populate the UI, and the logic to `Run` the step.
In our example, we will implement a step that will check if the `security.secret_key` is set correctly. In case it's not correct, we recommend the user to follow the documentation.
Check [`security_config_step.go`](./pkg/app/checks/configchecks/security_config_step.go) for the full implementation.
## Best Practices
1. **Error Handling**: In general, avoid returning errors for known issues, these will mark the check report as failed and the UI will render an error page. Only unexpected errors should be returned.
2. **Type Safety**: Use type assertions to ensure you're working with the correct type of item.
3. **Severity Levels**: Use appropriate severity levels:
- `CheckReportFailureSeverityHigh`: For critical issues that need immediate attention
- `CheckReportFailureSeverityLow`: For non-critical issues that can be addressed later
4. **Resolution Links**: Provide helpful links in the `CheckErrorLink` slice to help users resolve issues.
5. **Logging**: Use the provided logger to log important information and errors.
## Testing
Create tests for your check and its steps to ensure they work as expected. Test both successful and failure scenarios.

@ -3,8 +3,8 @@ module github.com/grafana/grafana/apps/advisor
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/klog/v2 v2.130.1 k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -45,12 +45,12 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openfga/openfga v1.8.12 // indirect github.com/openfga/openfga v1.8.13 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
@ -74,13 +74,13 @@ require (
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/grpc v1.72.0 // indirect google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.3 // indirect k8s.io/api v0.33.1 // indirect
k8s.io/apiextensions-apiserver v0.32.3 // indirect k8s.io/apiextensions-apiserver v0.33.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect

@ -107,6 +107,8 @@ github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/openfga/openfga v1.8.12 h1:xEirA6tFwaJfjBDtbHWCK0/Tw+B8XleRyhg9dcEpzHo= github.com/openfga/openfga v1.8.12 h1:xEirA6tFwaJfjBDtbHWCK0/Tw+B8XleRyhg9dcEpzHo=
github.com/openfga/openfga v1.8.12/go.mod h1:fIZyekdNB+tWQ6zIiglZonAc5ErZiDGMeHue/BzRYRM= github.com/openfga/openfga v1.8.12/go.mod h1:fIZyekdNB+tWQ6zIiglZonAc5ErZiDGMeHue/BzRYRM=
github.com/openfga/openfga v1.8.13 h1:ROURkotKhbmtyBX3188+cNElN8AOZmTl0CMkxUqwawo=
github.com/openfga/openfga v1.8.13/go.mod h1:h1VGcVW81eY1YyDtFx5+gxxAIEhIiOGR9SRGgs/X/k8=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -126,6 +128,7 @@ github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkq
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
@ -259,6 +262,7 @@ google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=

@ -3,6 +3,7 @@ package checkregistry
import ( import (
"github.com/grafana/grafana/apps/advisor/pkg/app/checks" "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/authchecks" "github.com/grafana/grafana/apps/advisor/pkg/app/checks/authchecks"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/configchecks"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/datasourcecheck" "github.com/grafana/grafana/apps/advisor/pkg/app/checks/datasourcecheck"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/plugincheck" "github.com/grafana/grafana/apps/advisor/pkg/app/checks/plugincheck"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
@ -27,19 +28,22 @@ type Service struct {
pluginContextProvider *plugincontext.Provider pluginContextProvider *plugincontext.Provider
pluginClient plugins.Client pluginClient plugins.Client
pluginRepo repo.Service pluginRepo repo.Service
pluginErrorResolver plugins.ErrorResolver
updateChecker pluginchecker.PluginUpdateChecker updateChecker pluginchecker.PluginUpdateChecker
pluginPreinstall pluginchecker.Preinstall pluginPreinstall pluginchecker.Preinstall
managedPlugins managedplugins.Manager managedPlugins managedplugins.Manager
provisionedPlugins provisionedplugins.Manager provisionedPlugins provisionedplugins.Manager
ssoSettingsSvc ssosettings.Service ssoSettingsSvc ssosettings.Service
GrafanaVersion string GrafanaVersion string
cfg *setting.Cfg
} }
func ProvideService(datasourceSvc datasources.DataSourceService, pluginStore pluginstore.Store, func ProvideService(datasourceSvc datasources.DataSourceService, pluginStore pluginstore.Store,
pluginContextProvider *plugincontext.Provider, pluginClient plugins.Client, pluginContextProvider *plugincontext.Provider, pluginClient plugins.Client,
updateChecker pluginchecker.PluginUpdateChecker, updateChecker pluginchecker.PluginUpdateChecker,
pluginRepo repo.Service, pluginPreinstall pluginchecker.Preinstall, managedPlugins managedplugins.Manager, pluginRepo repo.Service, pluginPreinstall pluginchecker.Preinstall, managedPlugins managedplugins.Manager,
provisionedPlugins provisionedplugins.Manager, ssoSettingsSvc ssosettings.Service, settings *setting.Cfg, provisionedPlugins provisionedplugins.Manager, ssoSettingsSvc ssosettings.Service, cfg *setting.Cfg,
pluginErrorResolver plugins.ErrorResolver,
) *Service { ) *Service {
return &Service{ return &Service{
datasourceSvc: datasourceSvc, datasourceSvc: datasourceSvc,
@ -47,12 +51,14 @@ func ProvideService(datasourceSvc datasources.DataSourceService, pluginStore plu
pluginContextProvider: pluginContextProvider, pluginContextProvider: pluginContextProvider,
pluginClient: pluginClient, pluginClient: pluginClient,
pluginRepo: pluginRepo, pluginRepo: pluginRepo,
pluginErrorResolver: pluginErrorResolver,
updateChecker: updateChecker, updateChecker: updateChecker,
pluginPreinstall: pluginPreinstall, pluginPreinstall: pluginPreinstall,
managedPlugins: managedPlugins, managedPlugins: managedPlugins,
provisionedPlugins: provisionedPlugins, provisionedPlugins: provisionedPlugins,
ssoSettingsSvc: ssoSettingsSvc, ssoSettingsSvc: ssoSettingsSvc,
GrafanaVersion: settings.BuildVersion, GrafanaVersion: cfg.BuildVersion,
cfg: cfg,
} }
} }
@ -70,9 +76,11 @@ func (s *Service) Checks() []checks.Check {
s.pluginStore, s.pluginStore,
s.pluginRepo, s.pluginRepo,
s.updateChecker, s.updateChecker,
s.pluginErrorResolver,
s.GrafanaVersion, s.GrafanaVersion,
), ),
authchecks.New(s.ssoSettingsSvc), authchecks.New(s.ssoSettingsSvc),
configchecks.New(s.cfg),
} }
} }

@ -30,7 +30,7 @@ func (c *check) ID() string {
} }
func (c *check) Name() string { func (c *check) Name() string {
return "SSO Setting" return "SSO setting"
} }
func (c *check) Init(ctx context.Context) error { func (c *check) Init(ctx context.Context) error {

@ -0,0 +1,48 @@
package configchecks
import (
"context"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/setting"
)
var _ checks.Check = (*check)(nil)
type check struct {
cfg *setting.Cfg
}
func New(cfg *setting.Cfg) checks.Check {
return &check{
cfg: cfg,
}
}
func (c *check) ID() string {
return "config"
}
func (c *check) Name() string {
return "config setting"
}
func (c *check) Items(ctx context.Context) ([]any, error) {
return []any{"security.secret_key"}, nil
}
func (c *check) Item(ctx context.Context, id string) (any, error) {
return id, nil
}
func (c *check) Init(ctx context.Context) error {
return nil
}
func (c *check) Steps() []checks.Step {
return []checks.Step{
&securityConfigStep{
securitySection: c.cfg.SectionWithEnvOverrides("security"),
},
}
}

@ -0,0 +1,73 @@
package configchecks
import (
"context"
"fmt"
"strings"
"github.com/grafana/grafana-app-sdk/logging"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/setting"
)
const (
// nolint:gosec // Defined in defaults.ini originally
defaultSecretKey = "SW2YcwTIb9zpOOhoPsMm"
)
type securityConfigStep struct {
securitySection *setting.DynamicSection
}
func (s *securityConfigStep) Title() string {
return "Security config check"
}
func (s *securityConfigStep) Description() string {
return "Check if the Grafana security config is set correctly."
}
func (s *securityConfigStep) Resolution() string {
return "Follow the documentation for each element."
}
func (s *securityConfigStep) ID() string {
return "security_config"
}
func (s *securityConfigStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, it any) ([]advisor.CheckReportFailure, error) {
itemPath, ok := it.(string)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
items := strings.Split(itemPath, ".")
if len(items) != 2 {
// Not interested in this item
return nil, nil
}
section, key := items[0], items[1]
if section != "security" {
// Only interested in security section
return nil, nil
}
if key == "secret_key" {
secretKey := s.securitySection.Key("secret_key").Value()
if secretKey == defaultSecretKey {
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
s.ID(),
"secret_key",
itemPath,
[]advisor.CheckErrorLink{
{
Message: "Avoid default value",
Url: "https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-database-encryption/",
},
},
)}, nil
}
}
return nil, nil
}

@ -0,0 +1,33 @@
package configchecks
import (
"context"
"testing"
"github.com/grafana/grafana-app-sdk/logging"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
func TestSecurityConfigStepSuccess(t *testing.T) {
cfg := setting.NewCfg()
step := &securityConfigStep{
securitySection: cfg.SectionWithEnvOverrides("security"),
}
errs, err := step.Run(context.Background(), logging.DefaultLogger, nil, "security.secret_key")
require.NoError(t, err)
require.Len(t, errs, 0)
}
func TestSecurityConfigStepFailure(t *testing.T) {
cfg := setting.NewCfg()
cfg.SectionWithEnvOverrides("security").Key("secret_key").SetValue(defaultSecretKey)
step := &securityConfigStep{
securitySection: cfg.SectionWithEnvOverrides("security"),
}
errs, err := step.Run(context.Background(), logging.DefaultLogger, nil, "security.secret_key")
require.NoError(t, err)
require.Len(t, errs, 1)
}

@ -88,7 +88,7 @@ func (c *check) ID() string {
} }
func (c *check) Name() string { func (c *check) Name() string {
return "Data Source" return "data source"
} }
func (c *check) Init(ctx context.Context) error { func (c *check) Init(ctx context.Context) error {

@ -2,43 +2,42 @@ package plugincheck
import ( import (
"context" "context"
"fmt"
sysruntime "runtime" sysruntime "runtime"
"github.com/grafana/grafana-app-sdk/logging"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks" "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/repo" "github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
) )
const ( const (
CheckID = "plugin" CheckID = "plugin"
DeprecationStepID = "deprecation"
UpdateStepID = "update"
) )
func New( func New(
pluginStore pluginstore.Store, pluginStore pluginstore.Store,
pluginRepo repo.Service, pluginRepo repo.Service,
updateChecker pluginchecker.PluginUpdateChecker, updateChecker pluginchecker.PluginUpdateChecker,
pluginErrorResolver plugins.ErrorResolver,
grafanaVersion string, grafanaVersion string,
) checks.Check { ) checks.Check {
return &check{ return &check{
PluginStore: pluginStore, PluginStore: pluginStore,
PluginRepo: pluginRepo, PluginRepo: pluginRepo,
GrafanaVersion: grafanaVersion, GrafanaVersion: grafanaVersion,
updateChecker: updateChecker, updateChecker: updateChecker,
pluginErrorResolver: pluginErrorResolver,
} }
} }
type check struct { type check struct {
PluginStore pluginstore.Store PluginStore pluginstore.Store
PluginRepo repo.Service PluginRepo repo.Service
updateChecker pluginchecker.PluginUpdateChecker updateChecker pluginchecker.PluginUpdateChecker
GrafanaVersion string pluginErrorResolver plugins.ErrorResolver
pluginIndex map[string]repo.PluginInfo GrafanaVersion string
pluginIndex map[string]repo.PluginInfo
} }
func (c *check) ID() string { func (c *check) ID() string {
@ -46,15 +45,43 @@ func (c *check) ID() string {
} }
func (c *check) Name() string { func (c *check) Name() string {
return "Plugin" return "plugin"
}
type pluginItem struct {
Plugin *pluginstore.Plugin
Err *plugins.Error
} }
func (c *check) Items(ctx context.Context) ([]any, error) { func (c *check) Items(ctx context.Context) ([]any, error) {
ps := c.PluginStore.Plugins(ctx) ps := c.PluginStore.Plugins(ctx)
res := make([]any, len(ps)) resMap := map[string]*pluginItem{}
for i, p := range ps { for _, p := range ps {
res[i] = p resMap[p.ID] = &pluginItem{
Plugin: &p,
Err: c.pluginErrorResolver.PluginError(ctx, p.ID),
}
}
// Plugins with errors are not added to the plugin store but
// we still want to show them in the check results so we add them to the map
pluginErrors := c.pluginErrorResolver.PluginErrors(ctx)
for _, e := range pluginErrors {
if _, exists := resMap[e.PluginID]; exists {
resMap[e.PluginID].Err = e
} else {
resMap[e.PluginID] = &pluginItem{
Plugin: nil,
Err: e,
}
}
}
res := make([]any, 0, len(resMap))
for _, p := range resMap {
res = append(res, p)
} }
return res, nil return res, nil
} }
@ -63,7 +90,10 @@ func (c *check) Item(ctx context.Context, id string) (any, error) {
if !exists { if !exists {
return nil, nil return nil, nil
} }
return p, nil return &pluginItem{
Plugin: &p,
Err: c.pluginErrorResolver.PluginError(ctx, p.ID),
}, nil
} }
func (c *check) Init(ctx context.Context) error { func (c *check) Init(ctx context.Context) error {
@ -99,117 +129,8 @@ func (c *check) Steps() []checks.Step {
updateChecker: c.updateChecker, updateChecker: c.updateChecker,
pluginIndex: c.pluginIndex, pluginIndex: c.pluginIndex,
}, },
&unsignedStep{
pluginIndex: c.pluginIndex,
},
} }
} }
type deprecationStep struct {
GrafanaVersion string
updateChecker pluginchecker.PluginUpdateChecker
pluginIndex map[string]repo.PluginInfo
}
func (s *deprecationStep) Title() string {
return "Deprecation check"
}
func (s *deprecationStep) Description() string {
return "Check if any installed plugins are deprecated."
}
func (s *deprecationStep) Resolution() string {
return "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do'" +
"target=_blank>documentation</a> for recommended steps or delete the plugin."
}
func (s *deprecationStep) ID() string {
return DeprecationStepID
}
func (s *deprecationStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, it any) ([]advisor.CheckReportFailure, error) {
p, ok := it.(pluginstore.Plugin)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
if !s.updateChecker.IsUpdatable(ctx, p) {
return nil, nil
}
// Check if plugin is deprecated
i, ok := s.pluginIndex[p.ID]
if !ok {
// Unable to check deprecation status
return nil, nil
}
if i.Status == "deprecated" {
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
s.ID(),
p.Name,
p.ID,
[]advisor.CheckErrorLink{
{
Message: "Admin",
Url: fmt.Sprintf("/plugins/%s", p.ID),
},
},
)}, nil
}
return nil, nil
}
type updateStep struct {
GrafanaVersion string
updateChecker pluginchecker.PluginUpdateChecker
pluginIndex map[string]repo.PluginInfo
}
func (s *updateStep) Title() string {
return "Update check"
}
func (s *updateStep) Description() string {
return "Checks if an installed plugins has a newer version available."
}
func (s *updateStep) Resolution() string {
return "Go to the plugin admin page and upgrade to the latest version."
}
func (s *updateStep) ID() string {
return UpdateStepID
}
func (s *updateStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, i any) ([]advisor.CheckReportFailure, error) {
p, ok := i.(pluginstore.Plugin)
if !ok {
return nil, fmt.Errorf("invalid item type %T", i)
}
if !s.updateChecker.IsUpdatable(ctx, p) {
return nil, nil
}
// Check if plugin has a newer version available
info, ok := s.pluginIndex[p.ID]
if !ok {
// Unable to check updates
return nil, nil
}
if s.updateChecker.CanUpdate(p.ID, p.Info.Version, info.Version, false) {
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityLow,
s.ID(),
p.Name,
p.ID,
[]advisor.CheckErrorLink{
{
Message: "Upgrade",
Url: fmt.Sprintf("/plugins/%s?page=version-history", p.ID),
},
},
)}, nil
}
return nil, nil
}

@ -23,6 +23,7 @@ func TestRun(t *testing.T) {
pluginPreinstalled []string pluginPreinstalled []string
pluginManaged []string pluginManaged []string
pluginProvisioned []string pluginProvisioned []string
pluginErrors []*plugins.Error
expectedFailures []advisor.CheckReportFailure expectedFailures []advisor.CheckReportFailure
}{ }{
{ {
@ -47,7 +48,7 @@ func TestRun(t *testing.T) {
Links: []advisor.CheckErrorLink{ Links: []advisor.CheckErrorLink{
{ {
Url: "/plugins/plugin1", Url: "/plugins/plugin1",
Message: "Admin", Message: "View plugin",
}, },
}, },
}, },
@ -119,6 +120,69 @@ func TestRun(t *testing.T) {
pluginProvisioned: []string{"plugin5"}, pluginProvisioned: []string{"plugin5"},
expectedFailures: []advisor.CheckReportFailure{}, expectedFailures: []advisor.CheckReportFailure{},
}, },
{
name: "Invalid signatures",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin6", Name: "Plugin 6", Info: plugins.Info{Version: "1.0.0"}}, Signature: plugins.SignatureStatusInvalid},
{JSONData: plugins.JSONData{ID: "plugin7", Name: "Plugin 7", Info: plugins.Info{Version: "1.0.0"}}, Signature: plugins.SignatureStatusModified},
{JSONData: plugins.JSONData{ID: "plugin8", Name: "Plugin 8", Info: plugins.Info{Version: "1.0.0"}}, Signature: plugins.SignatureStatusUnsigned},
},
pluginInfo: []repo.PluginInfo{
{Status: "active", Slug: "plugin6", Version: "1.0.0"},
{Status: "active", Slug: "plugin7", Version: "1.0.0"},
{Status: "active", Slug: "plugin8", Version: "1.0.0"},
},
pluginErrors: []*plugins.Error{
{PluginID: "plugin9", ErrorCode: plugins.ErrorCodeSignatureInvalid},
{PluginID: "plugin10", ErrorCode: plugins.ErrorCodeSignatureModified},
{PluginID: "plugin11", ErrorCode: plugins.ErrorCodeSignatureMissing},
{PluginID: "plugin12", ErrorCode: plugins.ErrorCodeFailedBackendStart}, // This should be ignored atm
},
expectedFailures: []advisor.CheckReportFailure{
{
Severity: advisor.CheckReportFailureSeverityLow,
StepID: UnsignedStepID,
Item: "Plugin 6",
ItemID: "plugin6",
Links: []advisor.CheckErrorLink{{Url: "/plugins/plugin6", Message: "View plugin"}},
},
{
Severity: advisor.CheckReportFailureSeverityLow,
StepID: UnsignedStepID,
Item: "Plugin 7",
ItemID: "plugin7",
Links: []advisor.CheckErrorLink{{Url: "/plugins/plugin7", Message: "View plugin"}},
},
{
Severity: advisor.CheckReportFailureSeverityLow,
StepID: UnsignedStepID,
Item: "Plugin 8",
ItemID: "plugin8",
Links: []advisor.CheckErrorLink{{Url: "/plugins/plugin8", Message: "View plugin"}},
},
{
Severity: advisor.CheckReportFailureSeverityHigh,
StepID: UnsignedStepID,
Item: "plugin9",
ItemID: "plugin9",
Links: []advisor.CheckErrorLink{},
},
{
Severity: advisor.CheckReportFailureSeverityHigh,
StepID: UnsignedStepID,
Item: "plugin10",
ItemID: "plugin10",
Links: []advisor.CheckErrorLink{},
},
{
Severity: advisor.CheckReportFailureSeverityHigh,
StepID: UnsignedStepID,
Item: "plugin11",
ItemID: "plugin11",
Links: []advisor.CheckErrorLink{},
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
@ -131,7 +195,8 @@ func TestRun(t *testing.T) {
managedPlugins := &mockManagedPlugins{managed: tt.pluginManaged} managedPlugins := &mockManagedPlugins{managed: tt.pluginManaged}
provisionedPlugins := &mockProvisionedPlugins{provisioned: tt.pluginProvisioned} provisionedPlugins := &mockProvisionedPlugins{provisioned: tt.pluginProvisioned}
updateChecker := pluginchecker.ProvideService(managedPlugins, provisionedPlugins, pluginPreinstall) updateChecker := pluginchecker.ProvideService(managedPlugins, provisionedPlugins, pluginPreinstall)
check := New(pluginStore, pluginRepo, updateChecker, "12.0.0") pluginErrorResolver := &mockPluginErrorResolver{pluginErrors: tt.pluginErrors}
check := New(pluginStore, pluginRepo, updateChecker, pluginErrorResolver, "12.0.0")
items, err := check.Items(context.Background()) items, err := check.Items(context.Background())
assert.NoError(t, err) assert.NoError(t, err)
@ -148,8 +213,8 @@ func TestRun(t *testing.T) {
} }
} }
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, len(tt.plugins), len(items)) assert.Equal(t, len(tt.plugins)+len(tt.pluginErrors), len(items))
assert.Equal(t, tt.expectedFailures, failures) assert.ElementsMatch(t, tt.expectedFailures, failures)
}) })
} }
} }
@ -222,3 +287,21 @@ type mockProvisionedPlugins struct {
func (m *mockProvisionedPlugins) ProvisionedPlugins(ctx context.Context) ([]string, error) { func (m *mockProvisionedPlugins) ProvisionedPlugins(ctx context.Context) ([]string, error) {
return m.provisioned, nil return m.provisioned, nil
} }
type mockPluginErrorResolver struct {
plugins.ErrorResolver
pluginErrors []*plugins.Error
}
func (m *mockPluginErrorResolver) PluginErrors(ctx context.Context) []*plugins.Error {
return m.pluginErrors
}
func (m *mockPluginErrorResolver) PluginError(ctx context.Context, id string) *plugins.Error {
for _, err := range m.pluginErrors {
if err.PluginID == id {
return err
}
}
return nil
}

@ -0,0 +1,76 @@
package plugincheck
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/logging"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker"
)
const (
DeprecationStepID = "deprecation"
)
type deprecationStep struct {
GrafanaVersion string
updateChecker pluginchecker.PluginUpdateChecker
pluginIndex map[string]repo.PluginInfo
}
func (s *deprecationStep) Title() string {
return "Deprecation check"
}
func (s *deprecationStep) Description() string {
return "Check if any installed plugins are deprecated."
}
func (s *deprecationStep) Resolution() string {
return "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do'" +
"target=_blank>documentation</a> for recommended steps or delete the plugin."
}
func (s *deprecationStep) ID() string {
return DeprecationStepID
}
func (s *deprecationStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, it any) ([]advisor.CheckReportFailure, error) {
pi, ok := it.(*pluginItem)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
p := pi.Plugin
if p == nil {
return nil, nil
}
if !s.updateChecker.IsUpdatable(ctx, *p) {
return nil, nil
}
// Check if plugin is deprecated
i, ok := s.pluginIndex[p.ID]
if !ok {
// Unable to check deprecation status
return nil, nil
}
if i.Status == "deprecated" {
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
s.ID(),
p.Name,
p.ID,
[]advisor.CheckErrorLink{
{
Message: "View plugin",
Url: fmt.Sprintf("/plugins/%s", p.ID),
},
},
)}, nil
}
return nil, nil
}

@ -0,0 +1,94 @@
package plugincheck
import (
"context"
"fmt"
"slices"
"github.com/grafana/grafana-app-sdk/logging"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/repo"
)
const (
UnsignedStepID = "unsigned"
)
type unsignedStep struct {
pluginIndex map[string]repo.PluginInfo
}
func (s *unsignedStep) Title() string {
return "Plugin signature check"
}
func (s *unsignedStep) Description() string {
return "Checks has a missing or invalid signature."
}
func (s *unsignedStep) Resolution() string {
return "For security, we recommend only installing plugins from the catalog. " +
"Review the plugin's status and verify your allowlist if appropriate."
}
func (s *unsignedStep) ID() string {
return UnsignedStepID
}
func (s *unsignedStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, it any) ([]advisor.CheckReportFailure, error) {
pi, ok := it.(*pluginItem)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
p := pi.Plugin
invalidSignatureTypes := []plugins.SignatureStatus{
plugins.SignatureStatusUnsigned,
plugins.SignatureStatusModified,
plugins.SignatureStatusInvalid,
}
if p != nil && slices.Contains(invalidSignatureTypes, p.Signature) {
// This will only happen in dev mode or if the plugin is in the unsigned allow list
links := []advisor.CheckErrorLink{}
if _, ok := s.pluginIndex[p.ID]; ok {
links = append(links, advisor.CheckErrorLink{
Message: "View plugin",
Url: fmt.Sprintf("/plugins/%s", p.ID),
})
}
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityLow,
s.ID(),
p.Name,
p.ID,
links,
)}, nil
}
pluginErr := pi.Err
invalidErrorCodeTypes := []plugins.ErrorCode{
plugins.ErrorCodeSignatureMissing,
plugins.ErrorCodeSignatureInvalid,
plugins.ErrorCodeSignatureModified,
}
if pluginErr != nil && slices.Contains(invalidErrorCodeTypes, pluginErr.ErrorCode) {
links := []advisor.CheckErrorLink{}
if _, ok := s.pluginIndex[pluginErr.PluginID]; ok {
links = append(links, advisor.CheckErrorLink{
Message: "View plugin",
Url: fmt.Sprintf("/plugins/%s", pluginErr.PluginID),
})
}
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
s.ID(),
pluginErr.PluginID,
pluginErr.PluginID,
links,
)}, nil
}
return nil, nil
}

@ -0,0 +1,76 @@
package plugincheck
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/logging"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker"
)
const (
UpdateStepID = "update"
)
type updateStep struct {
GrafanaVersion string
updateChecker pluginchecker.PluginUpdateChecker
pluginIndex map[string]repo.PluginInfo
}
func (s *updateStep) Title() string {
return "Update check"
}
func (s *updateStep) Description() string {
return "Checks if an installed plugins has a newer version available."
}
func (s *updateStep) Resolution() string {
return "Go to the plugin admin page and upgrade to the latest version."
}
func (s *updateStep) ID() string {
return UpdateStepID
}
func (s *updateStep) Run(ctx context.Context, log logging.Logger, _ *advisor.CheckSpec, it any) ([]advisor.CheckReportFailure, error) {
pi, ok := it.(*pluginItem)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
p := pi.Plugin
if p == nil {
return nil, nil
}
if !s.updateChecker.IsUpdatable(ctx, *p) {
return nil, nil
}
// Check if plugin has a newer version available
info, ok := s.pluginIndex[p.ID]
if !ok {
// Unable to check updates
return nil, nil
}
if s.updateChecker.CanUpdate(p.ID, p.Info.Version, info.Version, false) {
return []advisor.CheckReportFailure{checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityLow,
s.ID(),
p.Name,
p.ID,
[]advisor.CheckErrorLink{
{
Message: "Upgrade",
Url: fmt.Sprintf("/plugins/%s?page=version-history", p.ID),
},
},
)}, nil
}
return nil, nil
}

@ -72,9 +72,12 @@ func (r *Runner) createOrUpdate(ctx context.Context, log logging.Logger, obj res
return err return err
} }
currentAnnotations := current.GetAnnotations() currentAnnotations := current.GetAnnotations()
if currentAnnotations == nil {
currentAnnotations = make(map[string]string)
}
annotations := obj.GetAnnotations() annotations := obj.GetAnnotations()
maps.Copy(annotations, currentAnnotations) maps.Copy(currentAnnotations, annotations)
obj.SetAnnotations(annotations) obj.SetAnnotations(currentAnnotations) // This will update the annotations in the object
_, err = r.client.Update(ctx, id, obj, resource.UpdateOptions{}) _, err = r.client.Update(ctx, id, obj, resource.UpdateOptions{})
if err != nil { if err != nil {
// Ignore the error, it's probably due to a race condition // Ignore the error, it's probably due to a race condition

@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.35.1 APP_SDK_VERSION := v0.38.2
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

@ -3,10 +3,10 @@ module github.com/grafana/grafana/apps/alerting/notifications
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
github.com/grafana/grafana-app-sdk/logging v0.35.1 github.com/grafana/grafana-app-sdk/logging v0.38.2
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/apiserver v0.32.3 k8s.io/apiserver v0.33.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -20,7 +20,7 @@ require (
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch v5.9.11+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.132.0 // indirect github.com/getkin/kin-openapi v0.132.0 // indirect
@ -29,22 +29,18 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference 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-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/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@ -61,18 +57,17 @@ require (
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/bbolt v1.4.0 // indirect go.etcd.io/bbolt v1.4.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect go.etcd.io/etcd/api/v3 v3.5.21 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
go.etcd.io/etcd/client/v3 v3.5.16 // indirect go.etcd.io/etcd/client/v3 v3.5.21 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
@ -93,9 +88,8 @@ require (
golang.org/x/term v0.32.0 // indirect golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // 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/api v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/grpc v1.72.1 // indirect google.golang.org/grpc v1.72.1 // indirect
@ -103,13 +97,13 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.3 // indirect k8s.io/api v0.33.1 // indirect
k8s.io/apiextensions-apiserver v0.32.3 // indirect k8s.io/apiextensions-apiserver v0.33.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/component-base v0.32.3 // indirect k8s.io/component-base v0.33.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect

@ -19,7 +19,6 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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.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 h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@ -32,8 +31,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
@ -56,8 +55,8 @@ github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@ -79,18 +78,16 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 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/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/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 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI= github.com/grafana/grafana-app-sdk v0.38.2 h1:raQ1mqCmNJ2AyCSV3m6ehFC0TGVZcqRcM6iOIDT6ZIE=
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.38.2/go.mod h1:LhZ4i2IXGnW5FF/jAczX7SnGFNai7x2qwB8YHNZWiZI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM= github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
github.com/grafana/grafana-app-sdk/logging v0.35.1/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk= github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
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 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-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= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
@ -104,8 +101,6 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -161,30 +156,29 @@ github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= 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/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -203,20 +197,20 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8=
go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28= go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY=
go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q= go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc=
go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs=
go.etcd.io/etcd/client/v2 v2.305.16 h1:kQrn9o5czVNaukf2A2At43cE9ZtWauOtf9vRZuiKXow= go.etcd.io/etcd/client/v2 v2.305.21 h1:eLiFfexc2mE+pTLz9WwnoEsX5JTTpLCYVivKkmVXIRA=
go.etcd.io/etcd/client/v2 v2.305.16/go.mod h1:h9YxWCzcdvZENbfzBTFCnoNumr2ax3F19sKMqHFmXHE= go.etcd.io/etcd/client/v2 v2.305.21/go.mod h1:OKkn4hlYNf43hpjEM3Ke3aRdUkhSl8xjKjSf8eCq2J8=
go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY=
go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU=
go.etcd.io/etcd/pkg/v3 v3.5.16 h1:cnavs5WSPWeK4TYwPYfmcr3Joz9BH+TZ6qoUtz6/+mc= go.etcd.io/etcd/pkg/v3 v3.5.21 h1:jUItxeKyrDuVuWhdh0HtjUANwyuzcb7/FAeUfABmQsk=
go.etcd.io/etcd/pkg/v3 v3.5.16/go.mod h1:+lutCZHG5MBBFI/U4eYT5yL7sJfnexsoM20Y0t2uNuY= go.etcd.io/etcd/pkg/v3 v3.5.21/go.mod h1:wpZx8Egv1g4y+N7JAsqi2zoUiBIUWznLjqJbylDjWgU=
go.etcd.io/etcd/raft/v3 v3.5.16 h1:zBXA3ZUpYs1AwiLGPafYAKKl/CORn/uaxYDwlNwndAk= go.etcd.io/etcd/raft/v3 v3.5.21 h1:dOmE0mT55dIUsX77TKBLq+RgyumsQuYeiRQnW/ylugk=
go.etcd.io/etcd/raft/v3 v3.5.16/go.mod h1:P4UP14AxofMJ/54boWilabqqWoW9eLodl6I5GdGzazI= go.etcd.io/etcd/raft/v3 v3.5.21/go.mod h1:fmcuY5R2SNkklU4+fKVBQi2biVp5vafMrWUEj4TJ4Cs=
go.etcd.io/etcd/server/v3 v3.5.16 h1:d0/SAdJ3vVsZvF8IFVb1k8zqMZ+heGcNfft71ul9GWE= go.etcd.io/etcd/server/v3 v3.5.21 h1:9w0/k12majtgarGmlMVuhwXRI2ob3/d1Ik3X5TKo0yU=
go.etcd.io/etcd/server/v3 v3.5.16/go.mod h1:ynhyZZpdDp1Gq49jkUg5mfkDWZwXnn3eIqCqtJnrD/s= go.etcd.io/etcd/server/v3 v3.5.21/go.mod h1:G1mOzdwuzKT1VRL7SqRchli/qcFrtLBTAQ4lV20sXXo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 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/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
@ -323,8 +317,8 @@ 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-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-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-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= 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 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= 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 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
@ -358,26 +352,26 @@ 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-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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/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.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
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/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
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/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= k8s.io/apiserver v0.33.1 h1:yLgLUPDVC6tHbNcw5uE9mo1T6ELhJj7B0geifra3Qdo=
k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= k8s.io/apiserver v0.33.1/go.mod h1:VMbE4ArWYLO01omz+k8hFjAdYfc3GVAYPrhP2tTKccs=
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
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/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= k8s.io/component-base v0.33.1 h1:EoJ0xA+wr77T+G8p6T3l4efT2oNwbqBVKR71E0tBIaI=
k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= k8s.io/component-base v0.33.1/go.mod h1:guT/w/6piyPfTgq7gfvgetyXMIh10zuXA6cRRm3rDuY=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 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 h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= 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 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= 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/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 v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=

@ -3,16 +3,16 @@ package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "notifications.alerting.grafana.app" APIGroup = "notifications.alerting.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v0alpha1" APIVersion = "v0alpha1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type ReceiverMetadata struct {
// NewReceiverMetadata creates a new ReceiverMetadata object. // NewReceiverMetadata creates a new ReceiverMetadata object.
func NewReceiverMetadata() *ReceiverMetadata { func NewReceiverMetadata() *ReceiverMetadata {
return &ReceiverMetadata{} return &ReceiverMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -13,7 +13,9 @@ type ReceiverIntegration struct {
// NewReceiverIntegration creates a new ReceiverIntegration object. // NewReceiverIntegration creates a new ReceiverIntegration object.
func NewReceiverIntegration() *ReceiverIntegration { func NewReceiverIntegration() *ReceiverIntegration {
return &ReceiverIntegration{} return &ReceiverIntegration{
Settings: map[string]interface{}{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -24,5 +26,7 @@ type ReceiverSpec struct {
// NewReceiverSpec creates a new ReceiverSpec object. // NewReceiverSpec creates a new ReceiverSpec object.
func NewReceiverSpec() *ReceiverSpec { func NewReceiverSpec() *ReceiverSpec {
return &ReceiverSpec{} return &ReceiverSpec{
Integrations: []ReceiverIntegration{},
}
} }

@ -24,5 +24,8 @@ type RoutingTreeMetadata struct {
// NewRoutingTreeMetadata creates a new RoutingTreeMetadata object. // NewRoutingTreeMetadata creates a new RoutingTreeMetadata object.
func NewRoutingTreeMetadata() *RoutingTreeMetadata { func NewRoutingTreeMetadata() *RoutingTreeMetadata {
return &RoutingTreeMetadata{} return &RoutingTreeMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -57,6 +57,7 @@ type RoutingTreeSpec struct {
func NewRoutingTreeSpec() *RoutingTreeSpec { func NewRoutingTreeSpec() *RoutingTreeSpec {
return &RoutingTreeSpec{ return &RoutingTreeSpec{
Defaults: *NewRoutingTreeRouteDefaults(), Defaults: *NewRoutingTreeRouteDefaults(),
Routes: []RoutingTreeRoute{},
} }
} }

@ -24,5 +24,8 @@ type TemplateGroupMetadata struct {
// NewTemplateGroupMetadata creates a new TemplateGroupMetadata object. // NewTemplateGroupMetadata creates a new TemplateGroupMetadata object.
func NewTemplateGroupMetadata() *TemplateGroupMetadata { func NewTemplateGroupMetadata() *TemplateGroupMetadata {
return &TemplateGroupMetadata{} return &TemplateGroupMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -24,5 +24,8 @@ type TimeIntervalMetadata struct {
// NewTimeIntervalMetadata creates a new TimeIntervalMetadata object. // NewTimeIntervalMetadata creates a new TimeIntervalMetadata object.
func NewTimeIntervalMetadata() *TimeIntervalMetadata { func NewTimeIntervalMetadata() *TimeIntervalMetadata {
return &TimeIntervalMetadata{} return &TimeIntervalMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -36,5 +36,7 @@ type TimeIntervalSpec struct {
// NewTimeIntervalSpec creates a new TimeIntervalSpec object. // NewTimeIntervalSpec creates a new TimeIntervalSpec object.
func NewTimeIntervalSpec() *TimeIntervalSpec { func NewTimeIntervalSpec() *TimeIntervalSpec {
return &TimeIntervalSpec{} return &TimeIntervalSpec{
TimeIntervals: []TimeIntervalInterval{},
}
} }

@ -6,12 +6,13 @@
package apis package apis
import ( import (
"encoding/json" "fmt"
"github.com/grafana/grafana-app-sdk/app" "github.com/grafana/grafana-app-sdk/app"
) "github.com/grafana/grafana-app-sdk/resource"
var () v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
var appManifestData = app.ManifestData{ var appManifestData = app.ManifestData{
AppName: "alerting", AppName: "alerting",
@ -72,12 +73,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 { func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData) return app.NewEmbeddedManifest(appManifestData)
} }
@ -85,3 +80,17 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest { func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("alerting") return app.NewAPIServerManifest("alerting")
} }
var kindVersionToGoType = map[string]resource.Kind{
"Receiver/v0alpha1": v0alpha1.ReceiverKind(),
"RoutingTree/v0alpha1": v0alpha1.RoutingTreeKind(),
"TemplateGroup/v0alpha1": v0alpha1.TemplateGroupKind(),
"TimeInterval/v0alpha1": v0alpha1.TimeIntervalKind(),
}
// 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
}

@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.35.1 APP_SDK_VERSION := v0.38.2
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

@ -4,11 +4,11 @@ go 1.24.3
require ( require (
cuelang.org/go v0.11.1 cuelang.org/go v0.11.1
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
github.com/grafana/grafana-plugin-sdk-go v0.277.0 github.com/grafana/grafana-plugin-sdk-go v0.277.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -26,7 +26,7 @@ require (
github.com/elazarl/goproxy v1.7.2 // indirect github.com/elazarl/goproxy v1.7.2 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/fatih/color v1.18.0 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.132.0 // indirect github.com/getkin/kin-openapi v0.132.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
@ -34,16 +34,17 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference 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-openapi/swag v0.23.0 // indirect
github.com/go-test/deep v1.1.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/flatbuffers v25.2.10+incompatible // indirect github.com/google/flatbuffers v25.2.10+incompatible // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/mux v1.8.1 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
github.com/grafana/otel-profiling-go v0.5.1 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect
@ -77,9 +78,9 @@ require (
github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect
@ -102,7 +103,7 @@ require (
go.opentelemetry.io/otel/sdk v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.6.0 // indirect go.opentelemetry.io/proto/otlp v1.6.0 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
golang.org/x/mod v0.24.0 // indirect golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect golang.org/x/oauth2 v0.29.0 // indirect
@ -113,6 +114,7 @@ require (
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect golang.org/x/tools v0.33.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gonum.org/v1/gonum v0.16.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // 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/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/grpc v1.72.1 // indirect google.golang.org/grpc v1.72.1 // indirect
@ -120,7 +122,7 @@ require (
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect

@ -46,8 +46,8 @@ github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= 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 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
@ -66,16 +66,16 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
@ -85,8 +85,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 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/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@ -94,14 +92,14 @@ 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/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 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI= github.com/grafana/grafana-app-sdk v0.38.2 h1:raQ1mqCmNJ2AyCSV3m6ehFC0TGVZcqRcM6iOIDT6ZIE=
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.38.2/go.mod h1:LhZ4i2IXGnW5FF/jAczX7SnGFNai7x2qwB8YHNZWiZI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM= github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
github.com/grafana/grafana-app-sdk/logging v0.35.1/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-plugin-sdk-go v0.277.0 h1:VDU2F4Y5NeRS//ejctdZtsAshrGaEdbtW33FsK0EQss= github.com/grafana/grafana-plugin-sdk-go v0.277.0 h1:VDU2F4Y5NeRS//ejctdZtsAshrGaEdbtW33FsK0EQss=
github.com/grafana/grafana-plugin-sdk-go v0.277.0/go.mod h1:mAUWg68w5+1f5TLDqagIr8sWr1RT9h7ufJl5NMcWJAU= github.com/grafana/grafana-plugin-sdk-go v0.277.0/go.mod h1:mAUWg68w5+1f5TLDqagIr8sWr1RT9h7ufJl5NMcWJAU=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 h1:kvG92f3XbJlQPUcZfXlTNLziI4e8LYeA9Jv2ixmM5Ic= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2/go.mod h1:ll14OJrUGYgXApz3YX6zmxYjRMZHL+pgQjoKBuRzaRs= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
@ -204,12 +202,12 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq7lB31IeJL8iy7jkUmU/PG1Sr8jVGhS749dbUA= github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq7lB31IeJL8iy7jkUmU/PG1Sr8jVGhS749dbUA=
github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c= github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@ -299,8 +297,8 @@ go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
@ -353,8 +351,8 @@ 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= 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 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= 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 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
@ -377,12 +375,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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
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/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
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/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 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 h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

@ -518,21 +518,8 @@ GridLayoutItemKind: {
spec: GridLayoutItemSpec spec: GridLayoutItemSpec
} }
GridLayoutRowKind: {
kind: "GridLayoutRow"
spec: GridLayoutRowSpec
}
GridLayoutRowSpec: {
y: int
collapsed: bool
title: string
elements: [...GridLayoutItemKind] // Grid items in the row will have their Y value be relative to the rows Y value. This means a panel positioned at Y: 0 in a row with Y: 10 will be positioned at Y: 11 (row header has a heigh of 1) in the dashboard.
repeat?: RowRepeatOptions
}
GridLayoutSpec: { GridLayoutSpec: {
items: [...GridLayoutItemKind | GridLayoutRowKind] items: [...GridLayoutItemKind]
} }
GridLayoutKind: { GridLayoutKind: {

@ -3,16 +3,16 @@ package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "dashboard.grafana.app" APIGroup = "dashboard.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v0alpha1" APIVersion = "v0alpha1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type DashboardMetadata struct {
// NewDashboardMetadata creates a new DashboardMetadata object. // NewDashboardMetadata creates a new DashboardMetadata object.
func NewDashboardMetadata() *DashboardMetadata { func NewDashboardMetadata() *DashboardMetadata {
return &DashboardMetadata{} return &DashboardMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -7,3 +7,4 @@ API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1,SortBy,Descending API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1,SortBy,Descending
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1,SortableField,Field API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1,SortableField,Field
API rule violation: names_match,github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1,Unstructured,Object API rule violation: names_match,github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1,Unstructured,Object
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1,DashboardList,ListMeta

@ -3,16 +3,16 @@ package v1beta1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "dashboard.grafana.app" APIGroup = "dashboard.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v1beta1" APIVersion = "v1beta1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type DashboardMetadata struct {
// NewDashboardMetadata creates a new DashboardMetadata object. // NewDashboardMetadata creates a new DashboardMetadata object.
func NewDashboardMetadata() *DashboardMetadata { func NewDashboardMetadata() *DashboardMetadata {
return &DashboardMetadata{} return &DashboardMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -1,3 +1,4 @@
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1,DashboardMetadata,Finalizers API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1,DashboardMetadata,Finalizers
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1,LibraryPanelStatus,Warnings API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1,LibraryPanelStatus,Warnings
API rule violation: names_match,github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1,Unstructured,Object API rule violation: names_match,github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1,Unstructured,Object
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1,DashboardList,ListMeta

@ -3,16 +3,16 @@ package v2alpha1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "dashboard.grafana.app" APIGroup = "dashboard.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v2alpha1" APIVersion = "v2alpha1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type DashboardMetadata struct {
// NewDashboardMetadata creates a new DashboardMetadata object. // NewDashboardMetadata creates a new DashboardMetadata object.
func NewDashboardMetadata() *DashboardMetadata { func NewDashboardMetadata() *DashboardMetadata {
return &DashboardMetadata{} return &DashboardMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -522,21 +522,8 @@ GridLayoutItemKind: {
spec: GridLayoutItemSpec spec: GridLayoutItemSpec
} }
GridLayoutRowKind: {
kind: "GridLayoutRow"
spec: GridLayoutRowSpec
}
GridLayoutRowSpec: {
y: int
collapsed: bool
title: string
elements: [...GridLayoutItemKind] // Grid items in the row will have their Y value be relative to the rows Y value. This means a panel positioned at Y: 0 in a row with Y: 10 will be positioned at Y: 11 (row header has a heigh of 1) in the dashboard.
repeat?: RowRepeatOptions
}
GridLayoutSpec: { GridLayoutSpec: {
items: [...GridLayoutItemKind | GridLayoutRowKind] items: [...GridLayoutItemKind]
} }
GridLayoutKind: { GridLayoutKind: {

@ -5,7 +5,6 @@ package v2alpha1
import ( import (
json "encoding/json" json "encoding/json"
errors "errors" errors "errors"
fmt "fmt"
) )
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -65,7 +64,9 @@ type DashboardDataQueryKind struct {
// NewDashboardDataQueryKind creates a new DashboardDataQueryKind object. // NewDashboardDataQueryKind creates a new DashboardDataQueryKind object.
func NewDashboardDataQueryKind() *DashboardDataQueryKind { func NewDashboardDataQueryKind() *DashboardDataQueryKind {
return &DashboardDataQueryKind{} return &DashboardDataQueryKind{
Spec: map[string]interface{}{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -80,6 +81,7 @@ type DashboardAnnotationPanelFilter struct {
func NewDashboardAnnotationPanelFilter() *DashboardAnnotationPanelFilter { func NewDashboardAnnotationPanelFilter() *DashboardAnnotationPanelFilter {
return &DashboardAnnotationPanelFilter{ return &DashboardAnnotationPanelFilter{
Exclude: (func(input bool) *bool { return &input })(false), Exclude: (func(input bool) *bool { return &input })(false),
Ids: []uint32{},
} }
} }
@ -133,6 +135,7 @@ type DashboardPanelSpec struct {
// NewDashboardPanelSpec creates a new DashboardPanelSpec object. // NewDashboardPanelSpec creates a new DashboardPanelSpec object.
func NewDashboardPanelSpec() *DashboardPanelSpec { func NewDashboardPanelSpec() *DashboardPanelSpec {
return &DashboardPanelSpec{ return &DashboardPanelSpec{
Links: []DashboardDataLink{},
Data: *NewDashboardQueryGroupKind(), Data: *NewDashboardQueryGroupKind(),
VizConfig: *NewDashboardVizConfigKind(), VizConfig: *NewDashboardVizConfigKind(),
} }
@ -174,7 +177,9 @@ type DashboardQueryGroupSpec struct {
// NewDashboardQueryGroupSpec creates a new DashboardQueryGroupSpec object. // NewDashboardQueryGroupSpec creates a new DashboardQueryGroupSpec object.
func NewDashboardQueryGroupSpec() *DashboardQueryGroupSpec { func NewDashboardQueryGroupSpec() *DashboardQueryGroupSpec {
return &DashboardQueryGroupSpec{ return &DashboardQueryGroupSpec{
QueryOptions: *NewDashboardQueryOptionsSpec(), Queries: []DashboardPanelQueryKind{},
Transformations: []DashboardTransformationKind{},
QueryOptions: *NewDashboardQueryOptionsSpec(),
} }
} }
@ -313,6 +318,7 @@ type DashboardVizConfigSpec struct {
// NewDashboardVizConfigSpec creates a new DashboardVizConfigSpec object. // NewDashboardVizConfigSpec creates a new DashboardVizConfigSpec object.
func NewDashboardVizConfigSpec() *DashboardVizConfigSpec { func NewDashboardVizConfigSpec() *DashboardVizConfigSpec {
return &DashboardVizConfigSpec{ return &DashboardVizConfigSpec{
Options: map[string]interface{}{},
FieldConfig: *NewDashboardFieldConfigSource(), FieldConfig: *NewDashboardFieldConfigSource(),
} }
} }
@ -331,7 +337,8 @@ type DashboardFieldConfigSource struct {
// NewDashboardFieldConfigSource creates a new DashboardFieldConfigSource object. // NewDashboardFieldConfigSource creates a new DashboardFieldConfigSource object.
func NewDashboardFieldConfigSource() *DashboardFieldConfigSource { func NewDashboardFieldConfigSource() *DashboardFieldConfigSource {
return &DashboardFieldConfigSource{ return &DashboardFieldConfigSource{
Defaults: *NewDashboardFieldConfig(), Defaults: *NewDashboardFieldConfig(),
Overrides: []DashboardV2alpha1FieldConfigSourceOverrides{},
} }
} }
@ -417,7 +424,8 @@ type DashboardValueMap struct {
// NewDashboardValueMap creates a new DashboardValueMap object. // NewDashboardValueMap creates a new DashboardValueMap object.
func NewDashboardValueMap() *DashboardValueMap { func NewDashboardValueMap() *DashboardValueMap {
return &DashboardValueMap{ return &DashboardValueMap{
Type: DashboardMappingTypeValue, Type: DashboardMappingTypeValue,
Options: map[string]DashboardValueMappingResult{},
} }
} }
@ -526,7 +534,9 @@ type DashboardThresholdsConfig struct {
// NewDashboardThresholdsConfig creates a new DashboardThresholdsConfig object. // NewDashboardThresholdsConfig creates a new DashboardThresholdsConfig object.
func NewDashboardThresholdsConfig() *DashboardThresholdsConfig { func NewDashboardThresholdsConfig() *DashboardThresholdsConfig {
return &DashboardThresholdsConfig{} return &DashboardThresholdsConfig{
Steps: []DashboardThreshold{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -688,12 +698,14 @@ func NewDashboardGridLayoutKind() *DashboardGridLayoutKind {
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type DashboardGridLayoutSpec struct { type DashboardGridLayoutSpec struct {
Items []DashboardGridLayoutItemKindOrGridLayoutRowKind `json:"items"` Items []DashboardGridLayoutItemKind `json:"items"`
} }
// NewDashboardGridLayoutSpec creates a new DashboardGridLayoutSpec object. // NewDashboardGridLayoutSpec creates a new DashboardGridLayoutSpec object.
func NewDashboardGridLayoutSpec() *DashboardGridLayoutSpec { func NewDashboardGridLayoutSpec() *DashboardGridLayoutSpec {
return &DashboardGridLayoutSpec{} return &DashboardGridLayoutSpec{
Items: []DashboardGridLayoutItemKind{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -758,46 +770,6 @@ func NewDashboardRepeatOptions() *DashboardRepeatOptions {
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
const DashboardRepeatMode = "variable" const DashboardRepeatMode = "variable"
// +k8s:openapi-gen=true
type DashboardGridLayoutRowKind struct {
Kind string `json:"kind"`
Spec DashboardGridLayoutRowSpec `json:"spec"`
}
// NewDashboardGridLayoutRowKind creates a new DashboardGridLayoutRowKind object.
func NewDashboardGridLayoutRowKind() *DashboardGridLayoutRowKind {
return &DashboardGridLayoutRowKind{
Kind: "GridLayoutRow",
Spec: *NewDashboardGridLayoutRowSpec(),
}
}
// +k8s:openapi-gen=true
type DashboardGridLayoutRowSpec struct {
Y int64 `json:"y"`
Collapsed bool `json:"collapsed"`
Title string `json:"title"`
// Grid items in the row will have their Y value be relative to the rows Y value. This means a panel positioned at Y: 0 in a row with Y: 10 will be positioned at Y: 11 (row header has a heigh of 1) in the dashboard.
Elements []DashboardGridLayoutItemKind `json:"elements"`
Repeat *DashboardRowRepeatOptions `json:"repeat,omitempty"`
}
// NewDashboardGridLayoutRowSpec creates a new DashboardGridLayoutRowSpec object.
func NewDashboardGridLayoutRowSpec() *DashboardGridLayoutRowSpec {
return &DashboardGridLayoutRowSpec{}
}
// +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{}
}
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type DashboardRowsLayoutKind struct { type DashboardRowsLayoutKind struct {
Kind string `json:"kind"` Kind string `json:"kind"`
@ -819,7 +791,9 @@ type DashboardRowsLayoutSpec struct {
// NewDashboardRowsLayoutSpec creates a new DashboardRowsLayoutSpec object. // NewDashboardRowsLayoutSpec creates a new DashboardRowsLayoutSpec object.
func NewDashboardRowsLayoutSpec() *DashboardRowsLayoutSpec { func NewDashboardRowsLayoutSpec() *DashboardRowsLayoutSpec {
return &DashboardRowsLayoutSpec{} return &DashboardRowsLayoutSpec{
Rows: []DashboardRowsLayoutRowKind{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -877,7 +851,9 @@ type DashboardConditionalRenderingGroupSpec struct {
// NewDashboardConditionalRenderingGroupSpec creates a new DashboardConditionalRenderingGroupSpec object. // NewDashboardConditionalRenderingGroupSpec creates a new DashboardConditionalRenderingGroupSpec object.
func NewDashboardConditionalRenderingGroupSpec() *DashboardConditionalRenderingGroupSpec { func NewDashboardConditionalRenderingGroupSpec() *DashboardConditionalRenderingGroupSpec {
return &DashboardConditionalRenderingGroupSpec{} return &DashboardConditionalRenderingGroupSpec{
Items: []DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -954,6 +930,17 @@ func NewDashboardConditionalRenderingTimeRangeSizeSpec() *DashboardConditionalRe
return &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{}
}
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type DashboardAutoGridLayoutKind struct { type DashboardAutoGridLayoutKind struct {
Kind string `json:"kind"` Kind string `json:"kind"`
@ -984,6 +971,7 @@ func NewDashboardAutoGridLayoutSpec() *DashboardAutoGridLayoutSpec {
return &DashboardAutoGridLayoutSpec{ return &DashboardAutoGridLayoutSpec{
MaxColumnCount: (func(input float64) *float64 { return &input })(3), MaxColumnCount: (func(input float64) *float64 { return &input })(3),
FillScreen: (func(input bool) *bool { return &input })(false), FillScreen: (func(input bool) *bool { return &input })(false),
Items: []DashboardAutoGridLayoutItemKind{},
} }
} }
@ -1047,7 +1035,9 @@ type DashboardTabsLayoutSpec struct {
// NewDashboardTabsLayoutSpec creates a new DashboardTabsLayoutSpec object. // NewDashboardTabsLayoutSpec creates a new DashboardTabsLayoutSpec object.
func NewDashboardTabsLayoutSpec() *DashboardTabsLayoutSpec { func NewDashboardTabsLayoutSpec() *DashboardTabsLayoutSpec {
return &DashboardTabsLayoutSpec{} return &DashboardTabsLayoutSpec{
Tabs: []DashboardTabsLayoutTabKind{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -1119,6 +1109,7 @@ type DashboardDashboardLink struct {
// NewDashboardDashboardLink creates a new DashboardDashboardLink object. // NewDashboardDashboardLink creates a new DashboardDashboardLink object.
func NewDashboardDashboardLink() *DashboardDashboardLink { func NewDashboardDashboardLink() *DashboardDashboardLink {
return &DashboardDashboardLink{ return &DashboardDashboardLink{
Tags: []string{},
AsDropdown: false, AsDropdown: false,
TargetBlank: false, TargetBlank: false,
IncludeVars: false, IncludeVars: false,
@ -1260,6 +1251,7 @@ func NewDashboardQueryVariableSpec() *DashboardQueryVariableSpec {
SkipUrlSync: false, SkipUrlSync: false,
Query: *NewDashboardDataQueryKind(), Query: *NewDashboardDataQueryKind(),
Regex: "", Regex: "",
Options: []DashboardVariableOption{},
Multi: false, Multi: false,
IncludeAll: false, IncludeAll: false,
AllowCustomValue: true, AllowCustomValue: true,
@ -1475,6 +1467,7 @@ func NewDashboardDatasourceVariableSpec() *DashboardDatasourceVariableSpec {
String: (func(input string) *string { return &input })(""), String: (func(input string) *string { return &input })(""),
}, },
}, },
Options: []DashboardVariableOption{},
Multi: false, Multi: false,
IncludeAll: false, IncludeAll: false,
Hide: DashboardVariableHideDontHide, Hide: DashboardVariableHideDontHide,
@ -1528,6 +1521,7 @@ func NewDashboardIntervalVariableSpec() *DashboardIntervalVariableSpec {
String: (func(input string) *string { return &input })(""), String: (func(input string) *string { return &input })(""),
}, },
}, },
Options: []DashboardVariableOption{},
Auto: false, Auto: false,
AutoMin: "", AutoMin: "",
AutoCount: 0, AutoCount: 0,
@ -1575,6 +1569,7 @@ func NewDashboardCustomVariableSpec() *DashboardCustomVariableSpec {
Name: "", Name: "",
Query: "", Query: "",
Current: *NewDashboardVariableOption(), Current: *NewDashboardVariableOption(),
Options: []DashboardVariableOption{},
Multi: false, Multi: false,
IncludeAll: false, IncludeAll: false,
Hide: DashboardVariableHideDontHide, Hide: DashboardVariableHideDontHide,
@ -1625,6 +1620,7 @@ func NewDashboardGroupByVariableSpec() *DashboardGroupByVariableSpec {
String: (func(input string) *string { return &input })(""), String: (func(input string) *string { return &input })(""),
}, },
}, },
Options: []DashboardVariableOption{},
Multi: false, Multi: false,
Hide: DashboardVariableHideDontHide, Hide: DashboardVariableHideDontHide,
SkipUrlSync: false, SkipUrlSync: false,
@ -1665,6 +1661,9 @@ type DashboardAdhocVariableSpec struct {
func NewDashboardAdhocVariableSpec() *DashboardAdhocVariableSpec { func NewDashboardAdhocVariableSpec() *DashboardAdhocVariableSpec {
return &DashboardAdhocVariableSpec{ return &DashboardAdhocVariableSpec{
Name: "", Name: "",
BaseFilters: []DashboardAdHocFilterWithLabels{},
Filters: []DashboardAdHocFilterWithLabels{},
DefaultKeys: []DashboardMetricFindValue{},
Hide: DashboardVariableHideDontHide, Hide: DashboardVariableHideDontHide,
SkipUrlSync: false, SkipUrlSync: false,
AllowCustomValue: true, AllowCustomValue: true,
@ -1752,11 +1751,16 @@ type DashboardSpec struct {
// NewDashboardSpec creates a new DashboardSpec object. // NewDashboardSpec creates a new DashboardSpec object.
func NewDashboardSpec() *DashboardSpec { func NewDashboardSpec() *DashboardSpec {
return &DashboardSpec{ return &DashboardSpec{
Annotations: []DashboardAnnotationQueryKind{},
CursorSync: DashboardDashboardCursorSyncOff, CursorSync: DashboardDashboardCursorSyncOff,
Editable: (func(input bool) *bool { return &input })(true), Editable: (func(input bool) *bool { return &input })(true),
Elements: map[string]DashboardElement{},
Layout: *NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(), Layout: *NewDashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(),
Links: []DashboardDashboardLink{},
Preload: false, Preload: false,
Tags: []string{},
TimeSettings: *NewDashboardTimeSettingsSpec(), TimeSettings: *NewDashboardTimeSettingsSpec(),
Variables: []DashboardVariableKind{},
} }
} }
@ -1769,7 +1773,8 @@ type DashboardV2alpha1FieldConfigSourceOverrides struct {
// NewDashboardV2alpha1FieldConfigSourceOverrides creates a new DashboardV2alpha1FieldConfigSourceOverrides object. // NewDashboardV2alpha1FieldConfigSourceOverrides creates a new DashboardV2alpha1FieldConfigSourceOverrides object.
func NewDashboardV2alpha1FieldConfigSourceOverrides() *DashboardV2alpha1FieldConfigSourceOverrides { func NewDashboardV2alpha1FieldConfigSourceOverrides() *DashboardV2alpha1FieldConfigSourceOverrides {
return &DashboardV2alpha1FieldConfigSourceOverrides{ return &DashboardV2alpha1FieldConfigSourceOverrides{
Matcher: *NewDashboardMatcherConfig(), Matcher: *NewDashboardMatcherConfig(),
Properties: []DashboardDynamicConfigValue{},
} }
} }
@ -1900,6 +1905,7 @@ func (resource DashboardPanelKindOrLibraryPanelKind) MarshalJSON() ([]byte, erro
if resource.LibraryPanelKind != nil { if resource.LibraryPanelKind != nil {
return json.Marshal(resource.LibraryPanelKind) return json.Marshal(resource.LibraryPanelKind)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -1917,7 +1923,7 @@ func (resource *DashboardPanelKindOrLibraryPanelKind) UnmarshalJSON(raw []byte)
discriminator, found := parsedAsMap["kind"] discriminator, found := parsedAsMap["kind"]
if !found { if !found {
return errors.New("discriminator field 'kind' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -1939,7 +1945,7 @@ func (resource *DashboardPanelKindOrLibraryPanelKind) UnmarshalJSON(raw []byte)
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator) return nil
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -1969,6 +1975,7 @@ func (resource DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap) MarshalJS
if resource.SpecialValueMap != nil { if resource.SpecialValueMap != nil {
return json.Marshal(resource.SpecialValueMap) return json.Marshal(resource.SpecialValueMap)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -1986,7 +1993,7 @@ func (resource *DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap) Unmarsha
discriminator, found := parsedAsMap["type"] discriminator, found := parsedAsMap["type"]
if !found { if !found {
return errors.New("discriminator field 'type' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -2024,68 +2031,7 @@ func (resource *DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap) Unmarsha
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `type = %v`", discriminator) return nil
}
// +k8s:openapi-gen=true
type DashboardGridLayoutItemKindOrGridLayoutRowKind struct {
GridLayoutItemKind *DashboardGridLayoutItemKind `json:"GridLayoutItemKind,omitempty"`
GridLayoutRowKind *DashboardGridLayoutRowKind `json:"GridLayoutRowKind,omitempty"`
}
// NewDashboardGridLayoutItemKindOrGridLayoutRowKind creates a new DashboardGridLayoutItemKindOrGridLayoutRowKind object.
func NewDashboardGridLayoutItemKindOrGridLayoutRowKind() *DashboardGridLayoutItemKindOrGridLayoutRowKind {
return &DashboardGridLayoutItemKindOrGridLayoutRowKind{}
}
// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardGridLayoutItemKindOrGridLayoutRowKind` as JSON.
func (resource DashboardGridLayoutItemKindOrGridLayoutRowKind) MarshalJSON() ([]byte, error) {
if resource.GridLayoutItemKind != nil {
return json.Marshal(resource.GridLayoutItemKind)
}
if resource.GridLayoutRowKind != nil {
return json.Marshal(resource.GridLayoutRowKind)
}
return []byte("null"), nil
}
// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardGridLayoutItemKindOrGridLayoutRowKind` from JSON.
func (resource *DashboardGridLayoutItemKindOrGridLayoutRowKind) 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 errors.New("discriminator field 'kind' not found in payload")
}
switch discriminator {
case "GridLayoutItem":
var dashboardGridLayoutItemKind DashboardGridLayoutItemKind
if err := json.Unmarshal(raw, &dashboardGridLayoutItemKind); err != nil {
return err
}
resource.GridLayoutItemKind = &dashboardGridLayoutItemKind
return nil
case "GridLayoutRow":
var dashboardGridLayoutRowKind DashboardGridLayoutRowKind
if err := json.Unmarshal(raw, &dashboardGridLayoutRowKind); err != nil {
return err
}
resource.GridLayoutRowKind = &dashboardGridLayoutRowKind
return nil
}
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator)
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -2115,6 +2061,7 @@ func (resource DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRows
if resource.RowsLayoutKind != nil { if resource.RowsLayoutKind != nil {
return json.Marshal(resource.RowsLayoutKind) return json.Marshal(resource.RowsLayoutKind)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -2132,7 +2079,7 @@ func (resource *DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRow
discriminator, found := parsedAsMap["kind"] discriminator, found := parsedAsMap["kind"]
if !found { if !found {
return errors.New("discriminator field 'kind' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -2170,7 +2117,7 @@ func (resource *DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRow
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator) return nil
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -2196,6 +2143,7 @@ func (resource DashboardConditionalRenderingVariableKindOrConditionalRenderingDa
if resource.ConditionalRenderingTimeRangeSizeKind != nil { if resource.ConditionalRenderingTimeRangeSizeKind != nil {
return json.Marshal(resource.ConditionalRenderingTimeRangeSizeKind) return json.Marshal(resource.ConditionalRenderingTimeRangeSizeKind)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -2213,7 +2161,7 @@ func (resource *DashboardConditionalRenderingVariableKindOrConditionalRenderingD
discriminator, found := parsedAsMap["kind"] discriminator, found := parsedAsMap["kind"]
if !found { if !found {
return errors.New("discriminator field 'kind' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -2243,7 +2191,7 @@ func (resource *DashboardConditionalRenderingVariableKindOrConditionalRenderingD
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator) return nil
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -2273,6 +2221,7 @@ func (resource DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabs
if resource.TabsLayoutKind != nil { if resource.TabsLayoutKind != nil {
return json.Marshal(resource.TabsLayoutKind) return json.Marshal(resource.TabsLayoutKind)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -2290,7 +2239,7 @@ func (resource *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTab
discriminator, found := parsedAsMap["kind"] discriminator, found := parsedAsMap["kind"]
if !found { if !found {
return errors.New("discriminator field 'kind' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -2328,7 +2277,7 @@ func (resource *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTab
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator) return nil
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -2374,6 +2323,7 @@ func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKin
if resource.AdhocVariableKind != nil { if resource.AdhocVariableKind != nil {
return json.Marshal(resource.AdhocVariableKind) return json.Marshal(resource.AdhocVariableKind)
} }
return []byte("null"), nil return []byte("null"), nil
} }
@ -2391,7 +2341,7 @@ func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKi
discriminator, found := parsedAsMap["kind"] discriminator, found := parsedAsMap["kind"]
if !found { if !found {
return errors.New("discriminator field 'kind' not found in payload") return nil
} }
switch discriminator { switch discriminator {
@ -2461,7 +2411,7 @@ func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKi
return nil return nil
} }
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator) return nil
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true

@ -56,13 +56,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2alpha1_DashboardFieldConfig(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2alpha1_DashboardFieldConfig(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2alpha1_DashboardFieldConfigSource(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2alpha1_DashboardFieldConfigSource(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemKind(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKindOrGridLayoutRowKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemKindOrGridLayoutRowKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemSpec(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemSpec(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKind(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutRowKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutRowKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutRowSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutRowSpec(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGroupByVariableKind(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2alpha1_DashboardGroupByVariableKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGroupByVariableSpec(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardGroupByVariableSpec(ref),
@ -2057,30 +2054,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemKind(ref common.R
} }
} }
func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemKindOrGridLayoutRowKind(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"GridLayoutItemKind": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind"),
},
},
"GridLayoutRowKind": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutRowKind"),
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutRowKind"},
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutItemSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{ return common.OpenAPIDefinition{
Schema: spec.Schema{ Schema: spec.Schema{
@ -2232,89 +2205,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutKindOrRowsLayoutKindO
} }
} }
func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutRowKind(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/v2alpha1.DashboardGridLayoutRowSpec"),
},
},
},
Required: []string{"kind", "spec"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutRowSpec"},
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutRowSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"y": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"collapsed": {
SchemaProps: spec.SchemaProps{
Default: false,
Type: []string{"boolean"},
Format: "",
},
},
"title": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"elements": {
SchemaProps: spec.SchemaProps{
Description: "Grid items in the row will have their Y value be relative to the rows Y value. This means a panel positioned at Y: 0 in a row with Y: 10 will be positioned at Y: 11 (row header has a heigh of 1) in the dashboard.",
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.DashboardGridLayoutItemKind"),
},
},
},
},
},
"repeat": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardRowRepeatOptions"),
},
},
},
Required: []string{"y", "collapsed", "title", "elements"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardRowRepeatOptions"},
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{ return common.OpenAPIDefinition{
Schema: spec.Schema{ Schema: spec.Schema{
@ -2327,7 +2217,8 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref common.Refer
Items: &spec.SchemaOrArray{ Items: &spec.SchemaOrArray{
Schema: &spec.Schema{ Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKindOrGridLayoutRowKind"), Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind"),
}, },
}, },
}, },
@ -2338,7 +2229,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardGridLayoutSpec(ref common.Refer
}, },
}, },
Dependencies: []string{ Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKindOrGridLayoutRowKind"}, "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardGridLayoutItemKind"},
} }
} }
@ -2390,6 +2281,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardGroupByVariableSpec(ref common.
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"), Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
}, },
}, },
"defaultValue": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"),
},
},
"current": { "current": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{}, Default: map[string]interface{}{},

@ -12,7 +12,6 @@ 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,DashboardFieldConfig,Links API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardFieldConfig,Links
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardFieldConfig,Mappings API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardFieldConfig,Mappings
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardFieldConfigSource,Overrides API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardFieldConfigSource,Overrides
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutRowSpec,Elements
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutSpec,Items API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutSpec,Items
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGroupByVariableSpec,Options API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGroupByVariableSpec,Options
API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardIntervalVariableSpec,Options API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardIntervalVariableSpec,Options
@ -36,8 +35,6 @@ API rule violation: list_type_missing,github.com/grafana/grafana/apps/dashboard/
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingDataKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingDataKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingTimeRangeSizeKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingTimeRangeSizeKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingVariableKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind,ConditionalRenderingVariableKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutItemKindOrGridLayoutRowKind,GridLayoutItemKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutItemKindOrGridLayoutRowKind,GridLayoutRowKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,AutoGridLayoutKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,AutoGridLayoutKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,GridLayoutKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,GridLayoutKind
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,RowsLayoutKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind,RowsLayoutKind
@ -66,3 +63,4 @@ API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/ap
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,RegexMap API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,RegexMap
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,SpecialValueMap API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,SpecialValueMap
API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,ValueMap API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap,ValueMap
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1,DashboardList,ListMeta

@ -6,13 +6,14 @@
package apis package apis
import ( import (
"encoding/json" "fmt"
"github.com/grafana/grafana-app-sdk/app" "github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/resource"
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"
) )
var ()
var appManifestData = app.ManifestData{ var appManifestData = app.ManifestData{
AppName: "dashboard", AppName: "dashboard",
Group: "dashboard.grafana.app", Group: "dashboard.grafana.app",
@ -38,12 +39,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 { func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData) return app.NewEmbeddedManifest(appManifestData)
} }
@ -51,3 +46,16 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest { func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("dashboard") return app.NewAPIServerManifest("dashboard")
} }
var kindVersionToGoType = map[string]resource.Kind{
"Dashboard/v0alpha1": v0alpha1.DashboardKind(),
"Dashboard/v1beta1": v1beta1.DashboardKind(),
"Dashboard/v2alpha1": v2alpha1.DashboardKind(),
}
// 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
}

@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.35.1 APP_SDK_VERSION := v0.38.2
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

@ -3,9 +3,9 @@ module github.com/grafana/grafana/apps/folder
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -20,10 +20,10 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference 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-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/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
@ -36,9 +36,9 @@ require (
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
@ -53,7 +53,7 @@ require (
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect

@ -20,28 +20,24 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= 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 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= 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.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 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI= github.com/grafana/grafana-app-sdk v0.38.2 h1:raQ1mqCmNJ2AyCSV3m6ehFC0TGVZcqRcM6iOIDT6ZIE=
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.38.2/go.mod h1:LhZ4i2IXGnW5FF/jAczX7SnGFNai7x2qwB8YHNZWiZI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM= github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
github.com/grafana/grafana-app-sdk/logging v0.35.1/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/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2 h1:kvG92f3XbJlQPUcZfXlTNLziI4e8LYeA9Jv2ixmM5Ic= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250422074709-7c8433fbb2c2/go.mod h1:ll14OJrUGYgXApz3YX6zmxYjRMZHL+pgQjoKBuRzaRs= 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= 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/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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -80,12 +76,12 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= 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 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 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 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
@ -154,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/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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
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/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
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/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 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 h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

@ -3,16 +3,16 @@ package v1beta1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "folder.grafana.app" APIGroup = "folder.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v1beta1" APIVersion = "v1beta1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type FolderMetadata struct {
// NewFolderMetadata creates a new FolderMetadata object. // NewFolderMetadata creates a new FolderMetadata object.
func NewFolderMetadata() *FolderMetadata { func NewFolderMetadata() *FolderMetadata {
return &FolderMetadata{} return &FolderMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -11,8 +11,8 @@ import (
) )
const ( const (
GROUP = Group GROUP = APIGroup
VERSION = Version VERSION = APIVersion
RESOURCE = "folders" RESOURCE = "folders"
APIVERSION = GROUP + "/" + VERSION APIVERSION = GROUP + "/" + VERSION
RESOURCEGROUP = RESOURCE + "." + GROUP RESOURCEGROUP = RESOURCE + "." + GROUP

@ -1,3 +1,4 @@
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,DescendantCounts,Counts API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,DescendantCounts,Counts
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderInfoList,Items API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderInfoList,Items
API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderMetadata,Finalizers API rule violation: list_type_missing,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderMetadata,Finalizers
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1,FolderList,ListMeta

@ -6,12 +6,13 @@
package apis package apis
import ( import (
"encoding/json" "fmt"
"github.com/grafana/grafana-app-sdk/app" "github.com/grafana/grafana-app-sdk/app"
) "github.com/grafana/grafana-app-sdk/resource"
var () v1beta1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
var appManifestData = app.ManifestData{ var appManifestData = app.ManifestData{
AppName: "folder", AppName: "folder",
@ -30,12 +31,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 { func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData) return app.NewEmbeddedManifest(appManifestData)
} }
@ -43,3 +38,14 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest { func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("folder") return app.NewAPIServerManifest("folder")
} }
var kindVersionToGoType = map[string]resource.Kind{
"Folder/v1beta1": v1beta1.FolderKind(),
}
// 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
}

@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.35.1 APP_SDK_VERSION := v0.38.2
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

@ -3,8 +3,8 @@ module github.com/grafana/grafana/apps/iam
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -19,10 +19,10 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference 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-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/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
@ -34,9 +34,9 @@ require (
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect
@ -50,7 +50,7 @@ require (
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect

@ -20,26 +20,22 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= 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 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= 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.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 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI= github.com/grafana/grafana-app-sdk v0.38.2 h1:raQ1mqCmNJ2AyCSV3m6ehFC0TGVZcqRcM6iOIDT6ZIE=
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.38.2/go.mod h1:LhZ4i2IXGnW5FF/jAczX7SnGFNai7x2qwB8YHNZWiZI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM= github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
github.com/grafana/grafana-app-sdk/logging v0.35.1/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk= github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 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/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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -78,17 +74,19 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= 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 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 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 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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.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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 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/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@ -150,12 +148,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/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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
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/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
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/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 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 h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

@ -3,16 +3,16 @@ package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "iam.grafana.app" APIGroup = "iam.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v0alpha1" APIVersion = "v0alpha1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type CoreRoleMetadata struct {
// NewCoreRoleMetadata creates a new CoreRoleMetadata object. // NewCoreRoleMetadata creates a new CoreRoleMetadata object.
func NewCoreRoleMetadata() *CoreRoleMetadata { func NewCoreRoleMetadata() *CoreRoleMetadata {
return &CoreRoleMetadata{} return &CoreRoleMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -30,5 +30,7 @@ type CoreRoleSpec struct {
// NewCoreRoleSpec creates a new CoreRoleSpec object. // NewCoreRoleSpec creates a new CoreRoleSpec object.
func NewCoreRoleSpec() *CoreRoleSpec { func NewCoreRoleSpec() *CoreRoleSpec {
return &CoreRoleSpec{} return &CoreRoleSpec{
Permissions: []CoreRolespecPermission{},
}
} }

@ -24,5 +24,8 @@ type GlobalRoleMetadata struct {
// NewGlobalRoleMetadata creates a new GlobalRoleMetadata object. // NewGlobalRoleMetadata creates a new GlobalRoleMetadata object.
func NewGlobalRoleMetadata() *GlobalRoleMetadata { func NewGlobalRoleMetadata() *GlobalRoleMetadata {
return &GlobalRoleMetadata{} return &GlobalRoleMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -30,5 +30,7 @@ type GlobalRoleSpec struct {
// NewGlobalRoleSpec creates a new GlobalRoleSpec object. // NewGlobalRoleSpec creates a new GlobalRoleSpec object.
func NewGlobalRoleSpec() *GlobalRoleSpec { func NewGlobalRoleSpec() *GlobalRoleSpec {
return &GlobalRoleSpec{} return &GlobalRoleSpec{
Permissions: []GlobalRolespecPermission{},
}
} }

@ -24,5 +24,8 @@ type GlobalRoleBindingMetadata struct {
// NewGlobalRoleBindingMetadata creates a new GlobalRoleBindingMetadata object. // NewGlobalRoleBindingMetadata creates a new GlobalRoleBindingMetadata object.
func NewGlobalRoleBindingMetadata() *GlobalRoleBindingMetadata { func NewGlobalRoleBindingMetadata() *GlobalRoleBindingMetadata {
return &GlobalRoleBindingMetadata{} return &GlobalRoleBindingMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -37,7 +37,8 @@ type GlobalRoleBindingSpec struct {
// NewGlobalRoleBindingSpec creates a new GlobalRoleBindingSpec object. // NewGlobalRoleBindingSpec creates a new GlobalRoleBindingSpec object.
func NewGlobalRoleBindingSpec() *GlobalRoleBindingSpec { func NewGlobalRoleBindingSpec() *GlobalRoleBindingSpec {
return &GlobalRoleBindingSpec{ return &GlobalRoleBindingSpec{
RoleRef: *NewGlobalRoleBindingspecRoleRef(), Subjects: []GlobalRoleBindingspecSubject{},
RoleRef: *NewGlobalRoleBindingspecRoleRef(),
} }
} }

@ -24,5 +24,8 @@ type ResourcePermissionMetadata struct {
// NewResourcePermissionMetadata creates a new ResourcePermissionMetadata object. // NewResourcePermissionMetadata creates a new ResourcePermissionMetadata object.
func NewResourcePermissionMetadata() *ResourcePermissionMetadata { func NewResourcePermissionMetadata() *ResourcePermissionMetadata {
return &ResourcePermissionMetadata{} return &ResourcePermissionMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -29,7 +29,9 @@ type ResourcePermissionspecPermission struct {
// NewResourcePermissionspecPermission creates a new ResourcePermissionspecPermission object. // NewResourcePermissionspecPermission creates a new ResourcePermissionspecPermission object.
func NewResourcePermissionspecPermission() *ResourcePermissionspecPermission { func NewResourcePermissionspecPermission() *ResourcePermissionspecPermission {
return &ResourcePermissionspecPermission{} return &ResourcePermissionspecPermission{
Verbs: []string{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
@ -41,7 +43,8 @@ type ResourcePermissionSpec struct {
// NewResourcePermissionSpec creates a new ResourcePermissionSpec object. // NewResourcePermissionSpec creates a new ResourcePermissionSpec object.
func NewResourcePermissionSpec() *ResourcePermissionSpec { func NewResourcePermissionSpec() *ResourcePermissionSpec {
return &ResourcePermissionSpec{ return &ResourcePermissionSpec{
Resource: *NewResourcePermissionspecResource(), Resource: *NewResourcePermissionspecResource(),
Permissions: []ResourcePermissionspecPermission{},
} }
} }

@ -24,5 +24,8 @@ type RoleMetadata struct {
// NewRoleMetadata creates a new RoleMetadata object. // NewRoleMetadata creates a new RoleMetadata object.
func NewRoleMetadata() *RoleMetadata { func NewRoleMetadata() *RoleMetadata {
return &RoleMetadata{} return &RoleMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -30,5 +30,7 @@ type RoleSpec struct {
// NewRoleSpec creates a new RoleSpec object. // NewRoleSpec creates a new RoleSpec object.
func NewRoleSpec() *RoleSpec { func NewRoleSpec() *RoleSpec {
return &RoleSpec{} return &RoleSpec{
Permissions: []RolespecPermission{},
}
} }

@ -24,5 +24,8 @@ type RoleBindingMetadata struct {
// NewRoleBindingMetadata creates a new RoleBindingMetadata object. // NewRoleBindingMetadata creates a new RoleBindingMetadata object.
func NewRoleBindingMetadata() *RoleBindingMetadata { func NewRoleBindingMetadata() *RoleBindingMetadata {
return &RoleBindingMetadata{} return &RoleBindingMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -37,7 +37,8 @@ type RoleBindingSpec struct {
// NewRoleBindingSpec creates a new RoleBindingSpec object. // NewRoleBindingSpec creates a new RoleBindingSpec object.
func NewRoleBindingSpec() *RoleBindingSpec { func NewRoleBindingSpec() *RoleBindingSpec {
return &RoleBindingSpec{ return &RoleBindingSpec{
RoleRef: *NewRoleBindingspecRoleRef(), Subjects: []RoleBindingspecSubject{},
RoleRef: *NewRoleBindingspecRoleRef(),
} }
} }

@ -6,12 +6,13 @@
package apis package apis
import ( import (
"encoding/json" "fmt"
"github.com/grafana/grafana-app-sdk/app" "github.com/grafana/grafana-app-sdk/app"
) "github.com/grafana/grafana-app-sdk/resource"
var () v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
)
var appManifestData = app.ManifestData{ var appManifestData = app.ManifestData{
AppName: "iam", AppName: "iam",
@ -85,12 +86,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 { func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData) return app.NewEmbeddedManifest(appManifestData)
} }
@ -98,3 +93,19 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest { func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("iam") return app.NewAPIServerManifest("iam")
} }
var kindVersionToGoType = map[string]resource.Kind{
"GlobalRole/v0alpha1": v0alpha1.GlobalRoleKind(),
"GlobalRoleBinding/v0alpha1": v0alpha1.GlobalRoleBindingKind(),
"CoreRole/v0alpha1": v0alpha1.CoreRoleKind(),
"Role/v0alpha1": v0alpha1.RoleKind(),
"RoleBinding/v0alpha1": v0alpha1.RoleBindingKind(),
"ResourcePermission/v0alpha1": v0alpha1.ResourcePermissionKind(),
}
// 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
}

@ -3,8 +3,8 @@ module github.com/grafana/grafana/apps/investigations
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/klog/v2 v2.130.1 k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -30,8 +30,8 @@ require (
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
github.com/grafana/authlib v0.0.0-20250515162837-2f4a8263eabb // indirect github.com/grafana/authlib v0.0.0-20250515162837-2f4a8263eabb // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -47,12 +47,12 @@ require (
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/onsi/ginkgo/v2 v2.22.2 // indirect github.com/onsi/ginkgo/v2 v2.22.2 // indirect
github.com/onsi/gomega v1.36.2 // indirect github.com/onsi/gomega v1.36.2 // indirect
github.com/openfga/openfga v1.8.12 // indirect github.com/openfga/openfga v1.8.13 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
@ -74,17 +74,17 @@ require (
golang.org/x/term v0.32.0 // indirect golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.32.0 // indirect golang.org/x/tools v0.33.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/grpc v1.72.0 // indirect google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.3 // indirect k8s.io/api v0.33.1 // indirect
k8s.io/apiextensions-apiserver v0.32.3 // indirect k8s.io/apiextensions-apiserver v0.33.1 // indirect
k8s.io/client-go v0.32.3 // indirect k8s.io/client-go v0.33.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect

@ -99,6 +99,8 @@ github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/openfga/openfga v1.8.12 h1:xEirA6tFwaJfjBDtbHWCK0/Tw+B8XleRyhg9dcEpzHo= github.com/openfga/openfga v1.8.12 h1:xEirA6tFwaJfjBDtbHWCK0/Tw+B8XleRyhg9dcEpzHo=
github.com/openfga/openfga v1.8.12/go.mod h1:fIZyekdNB+tWQ6zIiglZonAc5ErZiDGMeHue/BzRYRM= github.com/openfga/openfga v1.8.12/go.mod h1:fIZyekdNB+tWQ6zIiglZonAc5ErZiDGMeHue/BzRYRM=
github.com/openfga/openfga v1.8.13 h1:ROURkotKhbmtyBX3188+cNElN8AOZmTl0CMkxUqwawo=
github.com/openfga/openfga v1.8.13/go.mod h1:h1VGcVW81eY1YyDtFx5+gxxAIEhIiOGR9SRGgs/X/k8=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -116,6 +118,7 @@ github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@ -200,6 +203,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -215,6 +219,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

@ -1,3 +1,29 @@
APP_SDK_VERSION := v0.38.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 .PHONY: generate
generate: generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generation
@grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none @$(APP_SDK_BIN) generate \
--source=./kinds/ \
--gogenpath=./pkg/apis \
--grouping=group \
--defencoding=none \
--noschemasinmanifest \
--postprocess

@ -3,9 +3,9 @@ module github.com/grafana/grafana/apps/playlist
go 1.24.3 go 1.24.3
require ( require (
github.com/grafana/grafana-app-sdk v0.35.1 github.com/grafana/grafana-app-sdk v0.38.2
k8s.io/apimachinery v0.32.3 k8s.io/apimachinery v0.33.1
k8s.io/client-go v0.32.3 k8s.io/client-go v0.33.1
k8s.io/klog/v2 v2.130.1 k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
) )
@ -17,7 +17,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch v5.9.11+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.132.0 // indirect github.com/getkin/kin-openapi v0.132.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
@ -25,14 +25,13 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference 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-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/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.35.1 // indirect github.com/grafana/grafana-app-sdk/logging v0.38.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -49,9 +48,9 @@ require (
github.com/onsi/gomega v1.36.2 // indirect github.com/onsi/gomega v1.36.2 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
@ -72,7 +71,6 @@ require (
golang.org/x/term v0.32.0 // indirect golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.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/api v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
@ -80,8 +78,8 @@ require (
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.3 // indirect k8s.io/api v0.33.1 // indirect
k8s.io/apiextensions-apiserver v0.32.3 // indirect k8s.io/apiextensions-apiserver v0.33.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect

@ -12,8 +12,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= 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 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
@ -31,8 +31,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@ -43,16 +43,14 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 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/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.35.1 h1:zEXubzsQrxGBOzXJJMBwhEClC/tvPi0sfK7NGmlX3RI= github.com/grafana/grafana-app-sdk v0.38.2 h1:raQ1mqCmNJ2AyCSV3m6ehFC0TGVZcqRcM6iOIDT6ZIE=
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.38.2/go.mod h1:LhZ4i2IXGnW5FF/jAczX7SnGFNai7x2qwB8YHNZWiZI=
github.com/grafana/grafana-app-sdk/logging v0.35.1 h1:taVpl+RoixTYl0JBJGhH+fPVmwA9wvdwdzJTZsv9buM= github.com/grafana/grafana-app-sdk/logging v0.38.2 h1:EdQTRxbbH72zdqJ09Z76zcSjfALJXkpPLgvKEPPnloc=
github.com/grafana/grafana-app-sdk/logging v0.35.1/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk= github.com/grafana/grafana-app-sdk/logging v0.38.2/go.mod h1:Y/bvbDhBiV/tkIle9RW49pgfSPIPSON8Q4qjx3pyqDk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= 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/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= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -102,12 +100,12 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@ -115,6 +113,8 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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.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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 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/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@ -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/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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
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/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
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/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
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/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 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 h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

@ -3,16 +3,16 @@ package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema" import "k8s.io/apimachinery/pkg/runtime/schema"
const ( const (
// Group is the API group used by all kinds in this package // APIGroup is the API group used by all kinds in this package
Group = "playlist.grafana.app" APIGroup = "playlist.grafana.app"
// Version is the API version used by all kinds in this package // APIVersion is the API version used by all kinds in this package
Version = "v0alpha1" APIVersion = "v0alpha1"
) )
var ( var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{ GroupVersion = schema.GroupVersion{
Group: Group, Group: APIGroup,
Version: Version, Version: APIVersion,
} }
) )

@ -24,5 +24,8 @@ type PlaylistMetadata struct {
// NewPlaylistMetadata creates a new PlaylistMetadata object. // NewPlaylistMetadata creates a new PlaylistMetadata object.
func NewPlaylistMetadata() *PlaylistMetadata { func NewPlaylistMetadata() *PlaylistMetadata {
return &PlaylistMetadata{} return &PlaylistMetadata{
Finalizers: []string{},
Labels: map[string]string{},
}
} }

@ -18,8 +18,11 @@ import (
type Playlist struct { type Playlist struct {
metav1.TypeMeta `json:",inline" yaml:",inline"` metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"` metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
Spec PlaylistSpec `json:"spec" yaml:"spec"`
PlaylistStatus PlaylistStatus `json:"status" yaml:"status"` // Spec is the spec of the Playlist
Spec PlaylistSpec `json:"spec" yaml:"spec"`
Status PlaylistStatus `json:"status" yaml:"status"`
} }
func (o *Playlist) GetSpec() any { func (o *Playlist) GetSpec() any {
@ -37,14 +40,14 @@ func (o *Playlist) SetSpec(spec any) error {
func (o *Playlist) GetSubresources() map[string]any { func (o *Playlist) GetSubresources() map[string]any {
return map[string]any{ return map[string]any{
"status": o.PlaylistStatus, "status": o.Status,
} }
} }
func (o *Playlist) GetSubresource(name string) (any, bool) { func (o *Playlist) GetSubresource(name string) (any, bool) {
switch name { switch name {
case "status": case "status":
return o.PlaylistStatus, true return o.Status, true
default: default:
return nil, false return nil, false
} }
@ -57,7 +60,7 @@ func (o *Playlist) SetSubresource(name string, value any) error {
if !ok { if !ok {
return fmt.Errorf("cannot set status type %#v, not of type PlaylistStatus", value) return fmt.Errorf("cannot set status type %#v, not of type PlaylistStatus", value)
} }
o.PlaylistStatus = cast o.Status = cast
return nil return nil
default: default:
return fmt.Errorf("subresource '%s' does not exist", name) return fmt.Errorf("subresource '%s' does not exist", name)
@ -219,6 +222,20 @@ func (o *Playlist) DeepCopyObject() runtime.Object {
return o.Copy() return o.Copy()
} }
func (o *Playlist) DeepCopy() *Playlist {
cpy := &Playlist{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *Playlist) DeepCopyInto(dst *Playlist) {
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 // Interface compliance compile-time check
var _ resource.Object = &Playlist{} var _ resource.Object = &Playlist{}
@ -262,5 +279,41 @@ func (o *PlaylistList) SetItems(items []resource.Object) {
} }
} }
func (o *PlaylistList) DeepCopy() *PlaylistList {
cpy := &PlaylistList{}
o.DeepCopyInto(cpy)
return cpy
}
func (o *PlaylistList) DeepCopyInto(dst *PlaylistList) {
resource.CopyObjectInto(dst, o)
}
// Interface compliance compile-time check // Interface compliance compile-time check
var _ resource.ListObject = &PlaylistList{} var _ resource.ListObject = &PlaylistList{}
// Copy methods for all subresource types
// DeepCopy creates a full deep copy of Spec
func (s *PlaylistSpec) DeepCopy() *PlaylistSpec {
cpy := &PlaylistSpec{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies Spec into another Spec object
func (s *PlaylistSpec) DeepCopyInto(dst *PlaylistSpec) {
resource.CopyObjectInto(dst, s)
}
// DeepCopy creates a full deep copy of PlaylistStatus
func (s *PlaylistStatus) DeepCopy() *PlaylistStatus {
cpy := &PlaylistStatus{}
s.DeepCopyInto(cpy)
return cpy
}
// DeepCopyInto deep copies PlaylistStatus into another PlaylistStatus object
func (s *PlaylistStatus) DeepCopyInto(dst *PlaylistStatus) {
resource.CopyObjectInto(dst, s)
}

@ -30,7 +30,9 @@ type PlaylistSpec struct {
// NewPlaylistSpec creates a new PlaylistSpec object. // NewPlaylistSpec creates a new PlaylistSpec object.
func NewPlaylistSpec() *PlaylistSpec { func NewPlaylistSpec() *PlaylistSpec {
return &PlaylistSpec{} return &PlaylistSpec{
Items: []PlaylistItem{},
}
} }
// +k8s:openapi-gen=true // +k8s:openapi-gen=true

@ -49,8 +49,9 @@ func schema_pkg_apis_playlist_v0alpha1_Playlist(ref common.ReferenceCallback) co
}, },
"spec": { "spec": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{}, Description: "Spec is the spec of the Playlist",
Ref: ref("github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1.PlaylistSpec"), Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1.PlaylistSpec"),
}, },
}, },
"status": { "status": {

@ -6,15 +6,12 @@
package apis package apis
import ( import (
"encoding/json" "fmt"
"github.com/grafana/grafana-app-sdk/app" "github.com/grafana/grafana-app-sdk/app"
) "github.com/grafana/grafana-app-sdk/resource"
var ( v0alpha1 "github.com/grafana/grafana/apps/playlist/pkg/apis/playlist/v0alpha1"
rawSchemaPlaylistv0alpha1 = []byte(`{"spec":{"properties":{"interval":{"type":"string"},"items":{"items":{"properties":{"type":{"description":"type of the item.","enum":["dashboard_by_tag","dashboard_by_uid","dashboard_by_id"],"type":"string"},"value":{"description":"Value depends on type and describes the playlist item.\n - dashboard_by_id: The value is an internal numerical identifier set by Grafana. This\n is not portable as the numerical identifier is non-deterministic between different instances.\n Will be replaced by dashboard_by_uid in the future. (deprecated)\n - dashboard_by_tag: The value is a tag which is set on any number of dashboards. All\n dashboards behind the tag will be added to the playlist.\n - dashboard_by_uid: The value is the dashboard UID","type":"string"}},"required":["type","value"],"type":"object"},"type":"array"},"title":{"type":"string"}},"required":["title","interval","items"],"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}}`)
versionSchemaPlaylistv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaPlaylistv0alpha1, &versionSchemaPlaylistv0alpha1)
) )
var appManifestData = app.ManifestData{ var appManifestData = app.ManifestData{
@ -42,19 +39,12 @@ var appManifestData = app.ManifestData{
}, },
}, },
}, },
Schema: &versionSchemaPlaylistv0alpha1,
}, },
}, },
}, },
}, },
} }
func jsonToMap(j string) map[string]any {
m := make(map[string]any)
json.Unmarshal([]byte(j), &j)
return m
}
func LocalManifest() app.Manifest { func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData) return app.NewEmbeddedManifest(appManifestData)
} }
@ -62,3 +52,14 @@ func LocalManifest() app.Manifest {
func RemoteManifest() app.Manifest { func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("playlist") return app.NewAPIServerManifest("playlist")
} }
var kindVersionToGoType = map[string]resource.Kind{
"Playlist/v0alpha1": v0alpha1.PlaylistKind(),
}
// 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
}

@ -812,6 +812,7 @@ client_id = some_client_id
client_secret = client_secret =
managed_identity_client_id = managed_identity_client_id =
federated_credential_audience = federated_credential_audience =
workload_identity_token_file = /var/run/secrets/azure/tokens/azure-identity-token
scopes = openid email profile scopes = openid email profile
auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
@ -1538,23 +1539,13 @@ max_annotations_to_keep =
rule_query_offset = 1m rule_query_offset = 1m
[recording_rules] [recording_rules]
# Enable recording rules. You must provide write credentials below. # Enable recording rules.
enabled = false enabled = true
# Target URL (including write path) for recording rules.
url =
# Optional username for basic authentication on recording rule write requests. Can be left blank to disable basic auth
basic_auth_username =
# Optional assword for basic authentication on recording rule write requests. Can be left blank.
basic_auth_password =
# Request timeout for recording rule writes. # Request timeout for recording rule writes.
timeout = 10s timeout = 10s
# Default data source UID to write to if not specified in the rule definition. # Default data source UID to write to if not specified in the rule definition.
# Only has effect if the grafanaManagedRecordingRulesDatasources feature toggle is enabled.
default_datasource_uid = default_datasource_uid =
# Optional custom headers to include in recording rule write requests. # Optional custom headers to include in recording rule write requests.
@ -1841,7 +1832,7 @@ forward_host_env_vars =
preinstall = preinstall =
# Comma separated list of plugin ids to install before the startup process # Comma separated list of plugin ids to install before the startup process
# These will be installed before starting Grafana. Useful when used with provisioning. # These will be installed before starting Grafana. Useful when used with provisioning.
preinstall_sync = preinstall_sync =
# Disables preinstall feature. It has the same effect as setting preinstall to an empty list. # Disables preinstall feature. It has the same effect as setting preinstall to an empty list.
preinstall_disabled = false preinstall_disabled = false
# Update strategy for plugins. # Update strategy for plugins.

@ -787,6 +787,7 @@
;client_secret = some_client_secret ;client_secret = some_client_secret
;managed_identity_client_id = ;managed_identity_client_id =
;federated_credential_audience = ;federated_credential_audience =
;workload_identity_token_file =
;scopes = openid email profile ;scopes = openid email profile
;auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize ;auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
;token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token ;token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
@ -1517,23 +1518,13 @@ rule_query_offset = 1m
#################################### Recording Rules ##################### #################################### Recording Rules #####################
[recording_rules] [recording_rules]
# Enable recording rules. You must provide write credentials below. # Enable recording rules.
enabled = false enabled = true
# Target URL (including write path) for recording rules.
url =
# Optional username for basic authentication on recording rule write requests. Can be left blank to disable basic auth
basic_auth_username =
# Optional assword for basic authentication on recording rule write requests. Can be left blank.
basic_auth_password =
# Request timeout for recording rule writes. # Request timeout for recording rule writes.
timeout = 30s timeout = 30s
# Default data source UID to write to if not specified in the rule definition. # Default data source UID to write to if not specified in the rule definition.
# Only has effect if the grafanaManagedRecordingRulesDatasources feature toggle is enabled.
default_datasource_uid = default_datasource_uid =
# Optional custom headers to include in recording rule write requests. # Optional custom headers to include in recording rule write requests.
@ -1787,7 +1778,7 @@ default_datasource_uid =
; preinstall = ; preinstall =
# Comma separated list of plugin ids to install before the startup process # Comma separated list of plugin ids to install before the startup process
# These will be installed before starting Grafana. Useful when used with provisioning. # These will be installed before starting Grafana. Useful when used with provisioning.
; preinstall_sync = ; preinstall_sync =
# Disables preinstall feature. It has the same effect as setting preinstall to an empty list. # Disables preinstall feature. It has the same effect as setting preinstall to an empty list.
; preinstall_disabled = false ; preinstall_disabled = false

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save