Compare commits

..

129 Commits

Author SHA1 Message Date
nmarrs 36b131b1b7 backport commit 2025-04-07 09:27:14 -05:00
Yuri Tseretyan aac667ec58 require editor to fetch config 2025-04-07 09:27:14 -05:00
Andres Martinez Gotor 4cc984f2c4 Sanitize paths before evaluating access to route 2025-04-07 09:27:14 -05:00
github-actions[bot] 4f00a8817e apply security patch: release-11.5.3/341-202503050903.patch
commit 0d4c8798648fa2a008f6f51dabe85d37ef5ff00c
Author: oscarkilhed <oscar.kilhed@grafana.com>
Date:   Fri Feb 28 16:32:58 2025 +0100

    Limit number of characters in the title
2025-03-25 19:59:36 +00:00
Isabel Matwawana c93a59f478 [release-11.5.3] Docs: bar gauge visualization refactor (#102828)
Docs: bar gauge visualization refactor (#102747)

* Added Config options heading and bumped heading levels

* Added empty Text size options section and updated Value options

* Updated bar gauge section

* Added missing options and removed screenshot

* Fixed Bar gauge options

* Added descriptions for Text size section

* Added links to text size section

* Fixed text size section

(cherry picked from commit 13058d2715)
2025-03-25 15:58:06 -04:00
Jacob Valdez 6ebb9eb01d [release-11.5.3] Docs: updating admonition shortcodes in plugin management (#102819)
Docs: updating admonition shortcodes in plugin management (#102817)

(cherry picked from commit 4dccc03fa2)
2025-03-25 14:05:36 -05:00
Denis Vodopianov 0f4c28b024 Chore: Disable go-lint step in release branches (#102717)
Chore: Remove golang-ci from release workflows
2025-03-24 16:59:35 +01:00
Denis Vodopianov 6932c6af7e Chore: Update CVE-affected dependencies (#102709)
Chore: Update CVE-affected golang-gwt dependencies
2025-03-24 16:23:58 +01:00
Kim Nylander c6d3c1e489 [release-11.5.3] docs: Span details includes events and links (#102658)
docs: Span details includes events and links (#102520)

* docs: Span details includes events and links

Adds to the explore trace integration information about trace span
events and links, which are also available in the trace view.

Signed-off-by: Alex Bikfalvi <alex.bikfalvi@grafana.com>

* Update trace-integration.md

* Apply suggestions from code review

* Fix prettier issues

Signed-off-by: Alex Bikfalvi <alex.bikfalvi@grafana.com>

---------

Signed-off-by: Alex Bikfalvi <alex.bikfalvi@grafana.com>
Co-authored-by: Kim Nylander <104772500+knylander-grafana@users.noreply.github.com>
(cherry picked from commit a5665c06cf)

Co-authored-by: Alex Bikfalvi <alex@bikfalvi.com>
2025-03-24 09:11:41 -04:00
Ashley Harrison 81b2e00f25 [release-11.5.3] LDAP test: Fix page crash (#102683)
* LDAP test: Fix page crash (#102587)

* fix translation code on ldap page causing crash

* move tooltip outside of trans

(cherry picked from commit 4f01c1aa88)

* pseudo translations
2025-03-24 10:09:59 +00:00
Jacob Valdez 5eaeb7f6aa [release-11.5.3] Docs: Cleaning up configure security hardening doc (#102637)
Docs: Cleaning up configure security hardening docs (#102567)

* Docs: Cleaning up configure security hardening docs

* Adjusting layout

(cherry picked from commit 7d435e5d84)
2025-03-21 12:51:20 -05:00
Victor Marin c98bb442fd [release-11.5.3] Dashboards: Fix missing v/e/i keybindings to return back to dashboard (#102365)
Dashboards: Fix missing `v/e/i` keybindings to return back to dashboard (#101876)

readd keybindings to return from edit/view/inspect modes

(cherry picked from commit 3e7626cc96)
2025-03-18 13:46:38 +00:00
Irene Rodríguez 4c88576d4b [release-11.5.3] Docs: Group Attribute Sync feature in private preview (#102094)
Docs: Group Attribute Sync feature in private preview (#101822)

* Docs: Group Attribute Sync feature in private preview

* add link & support note

* update GAS API docs

(cherry picked from commit ff10186db7)

Co-authored-by: colin-stuart <colindonstuart@gmail.com>
2025-03-14 14:51:20 +01:00
Denis Vodopianov 510b8b66ff [release-11.5.3] Chore: update golang version in .drone.yaml (#102133) 2025-03-14 13:57:44 +01:00
Pepe Cano 46a2949ceb [release-11.5.3] docs(alerting): timing options minor enhancements (#102143)
docs(alerting): timing options minor enhancements (#101965)

* docs(alerting): timing options minor enhancements

* minor addition

* Update docs/sources/alerting/fundamentals/notifications/group-alert-notifications.md

Co-authored-by: Johnny Kartheiser <140559259+JohnnyK-Grafana@users.noreply.github.com>

---------

Co-authored-by: Johnny Kartheiser <140559259+JohnnyK-Grafana@users.noreply.github.com>
(cherry picked from commit 9452069745)
2025-03-14 12:06:42 +01:00
Pepe Cano 28b0f2d2e4 [release-11.5.3] docs(alerting): add notification screenshots details in Create and link alert rules to panels (#102134)
docs(alerting): add notification screenshots details in `Create and link alert rules to panels` (#102103)

* format admonition

* include mention to display panel screenshots in notifications

(cherry picked from commit 65d047dd43)
2025-03-14 12:06:14 +01:00
Pepe Cano b4eb5f1304 [release-11.5.3] docs(alerting): minor enhancements to intro concepts and example (#102068)
docs(alerting): minor enhancements to intro concepts and example (#102023)

* docs(alerting): minor enhancements to intro concepts and example

* Update docs/sources/alerting/fundamentals/alert-rules/annotation-label.md

Co-authored-by: Johnny Kartheiser <140559259+JohnnyK-Grafana@users.noreply.github.com>

---------

Co-authored-by: Johnny Kartheiser <140559259+JohnnyK-Grafana@users.noreply.github.com>
(cherry picked from commit 64b65ffc72)
2025-03-13 17:21:05 +01:00
Ashley Harrison be1aa19642 [release-11.5.3] Org redirection: Fix linking between orgs (#102089)
Org redirection: Fix linking between orgs (#102021)

* don't trim path

* add unit test

(cherry picked from commit f3fb9592da)
2025-03-13 12:15:42 +02:00
Pepe Cano 4da21c2a61 [release-11.5.3] docs(alerting): alert instance state resets when rule changes (#102065)
docs(alerting): alert instance state resets when rule changes (#102038)

* docs(alerting): alert instance state resets when rule changes

* specify that annotations updates are not affected

* enumerate exception fields

(cherry picked from commit 3e1513a6df)
2025-03-12 22:56:13 +01:00
Pepe Cano 4aa5ea2ea6 [release-11.5.3] docs(alerting): clarify behaviour when provisioning the policy tree (#101954)
docs(alerting): clarify behaviour when provisioning the policy tree (#101937)

(cherry picked from commit 5bfe046da9)
2025-03-11 16:56:36 +01:00
Isabel Matwawana c85946bee0 [release-11.5.3] Docs: Add enterprise availability notes (#101911)
Docs: Add enterprise availability notes (#101909)

* Added enterprise only note

* Fixed wording

* Added availability to share panel internally and removed invite new member

* Fixed wording for consistency

* Removed link to invite new members section

* Discarded change

(cherry picked from commit 1e6aa27313)
2025-03-10 16:51:32 -04:00
Pepe Cano ab8e58e805 [release-11.5.3] Alerting docs: clarify values included in Alert.Labels and Alert.Values (#101873)
Alerting docs: clarify values included in `Alert.Labels` and `Alert.Values` (#101571)

* Alerting docs: clarify values included in `Alert.Labels` and `Alert.Values`

* minor change

(cherry picked from commit 5fb8540230)
2025-03-10 15:45:13 +01:00
Pepe Cano 45316fdd04 [release-11.5.3] Alerting docs: clarify the export JSON format are for file provisioning (#101872)
Alerting docs: clarify the `export` JSON format are for file provisioning (#101617)

* Remove unused `Separator` column

* Clarify the `export` JSON output is for file provisioning

* minor copy changes

* Be more specific about the `X-Disable-Provenance` header

* minor change

* fix vale errors

* Set inline code format in property names

* fix vale error: `bool`

(cherry picked from commit 97d16c7a7b)
2025-03-10 12:32:47 +01:00
grafana-delivery-bot[bot] 1bcc80daa7 [release-11.5.3] Alerting docs: dynamic label changes (#101866)
Alerting docs: dynamic label changes (#101781)

(cherry picked from commit 23ccd2be95)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-03-10 11:54:15 +01:00
grafana-delivery-bot[bot] dcb1180f28 [release-11.5.3] Alerting docs: clarify No data/Error alerts skip pending period (#101867)
Alerting docs: clarify `No data/Error` alerts skip pending period (#101431)

* Alerting docs: clarify `No data/Error` alerts skip pending period

* fix vale errors

(cherry picked from commit a800f87064)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-03-10 11:53:34 +01:00
grafana-delivery-bot[bot] 7abc79cb2e [release-11.5.3] Alerting: Re-encrypt existing contact points before get and patch in legacy config API (#101819)
Alerting: Re-encrypt existing contact points before get and patch in legacy config API (#101263)

* Test covering Get+Save interaction for newly secret fields

* Alerting: Re-encrypt existing contact points before get and patch

(cherry picked from commit b73c59547c)

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
2025-03-07 17:23:45 -05:00
Isabel Matwawana ff47af1fba [release-11.5.3] Docs: traces visualization refactor (#101833)
Docs: traces visualization refactor (#101476)

* Added Config options heading, bumped heading levels, and changed heading

* Updated task sub-heading and added to do notes

* Moved span filter options into a table and moved sentences after table

* Removed image

* Replaced captions with alt text

* Updated image path for main screenshot

* Fixed image path

* Updated screenshot and made to do notes

* Updated link to new heading

* Removed comments

(cherry picked from commit b26fdf8f5e)
2025-03-07 16:50:57 -05:00
Robby Milo 96d15d9091 [v11.5] Remove relref shortcodes (#101707)
* manually replce all shared relrefs

* relref replace - grafana v11.5

* Merge branch 'master' into robbymilo/relref-replace-grafana-11.5

* manual fixes

* replace ref shortcodes

* Merge branch 'master' into robbymilo/relref-replace-grafana-11.5

* update readme

* update test

---------

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
2025-03-06 17:48:00 +02:00
grafana-delivery-bot[bot] fe4442a7fb [release-11.5.3] Add LOKI_VERSION and ONCALL_VERSION (#101685)
Add LOKI_VERSION and ONCALL_VERSION  (#101684)

* Add LOKI_VERSION

* Add ONCALL_VERSION

(cherry picked from commit beb884292e)

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
2025-03-06 13:29:36 +02:00
grafana-delivery-bot[bot] 3c7cdb103a [release-11.5.3] Azure: Update metric namespaces (#101662)
Azure: Update metric namespaces (#101644)

Update namespaces

(cherry picked from commit fbb6802195)

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
2025-03-06 09:27:11 +00:00
Matheus Macabu cd63f38f47 [release-11.5.3] Chore: Bump dependencies to address security issues (#101627)
* Chore: Bump github.com/go-jose/go-jose/v3 to v3.0.4

* Chore: Bump github.com/ua-parser/uap-go to v0.0.0-20250213224047-9c035f085b90

* Chore: Bump golang.org/x/net to v0.36.0

* Chore: Use github.com/moby/moby version 27.4.1 instead of 26.0.0

* Chore: Bump github.com/openfga/openfga to v1.8.5
2025-03-06 10:12:17 +01:00
Isabel Matwawana e166f06bfa [release-11.5.3] Docs: Fix broken profiling link (#101654)
Docs: Fix broken profiling link (#101637)

Fixed broken link

(cherry picked from commit 5ffca57a5d)
2025-03-05 15:38:48 -05:00
grafana-delivery-bot[bot] c80a182e3c [release-11.5.3] Docs: Fix typo in Drilldown note (#101647)
Docs: Fix typo in Drilldown note (#101579)

docs: Fix typo in Drilldown note
(cherry picked from commit 8832aa2aa2)

Co-authored-by: J Stickler <julie.stickler@grafana.com>
2025-03-05 21:44:49 +02:00
Matheus Macabu 29d35ec39c [release-11.5.3] Chore: Bump Go to 1.23.7 (#101581)
Chore: Bump Go to 1.23.7
2025-03-05 09:59:05 +01:00
grafana-delivery-bot[bot] 596b3e42f5 [release-11.5.3] Azure: Correctly set instance settings based on new credentials (#101563)
Azure: Correctly set instance settings based on new credentials (#99112)

Correctly set value based on new credentials

(cherry picked from commit f39c5bb45c)

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
2025-03-04 17:10:25 +00:00
Isabel Matwawana 027524dd98 Docs: Fix broken links (#101388)
Fixed broken links
2025-02-27 10:49:07 -05:00
Jev Forsberg 2ece5c261b [release-11.5.3] Chore: Update base alpine docker image (#101330)
Chore: Update base alpine docker image (#101320)

* baldm0mma/ update base image arg

* baldm0mma/ update alpine image

* baldm0mma/ skip failing test

* baldm0mma/ specifiy patch

* baldm0mma/ flaky test?

(cherry picked from commit a7ecb19c31)
2025-02-26 08:18:41 -07:00
Matheus Macabu 9db9662213 [release-11.5.3] Chore: Update golang.org/x/crypto and golang.org/x/oauth2 to address security issues (#101278)
Chore: Update golang.org/x/crypto and golang.org/x/ouath2 to address security issues (#101268)

- CVE-2025-22869 and Go issue https://go.dev/issue/71931.
- CVE-2025-22868 and Go issue https://go.dev/issue/71490.

(cherry picked from commit 3aedb9159e)
2025-02-26 08:42:00 +01:00
Jack Baldry 478ab85845 [release-11.5.3] Rename Explore Apps to App Drilldown (#101259)
Co-authored-by: Carl Bergquist <carl.bergquist@gmail.com>
Co-authored-by: Kim Nylander <104772500+knylander-grafana@users.noreply.github.com>
2025-02-25 04:03:36 +02:00
Kevin Minehart e79330dc08 [release-11.5.3] CI: Remove unused release_publisher scripts (#101158)
* CI: Remove unused release_publisher scripts (#101019)

* Remove the unused `release_publisher` script.
* Remove the "whats new check" in Drone.
* Automatically set the What's New URL in releases based on the tagged version.

(cherry picked from commit 49e5f77dd1)

* rerun?
2025-02-24 18:57:34 +02:00
Kim Nylander b4da2b9b2d [release-11.5.3] [DOC] Add shared note for Explore app rename to Drilldown (#101183) 2025-02-24 17:36:05 +02:00
Larissa Wandzura 3c71bd0a5c [release-11.5.3] Docs: Overhaul of PostgreSQL data source documentation (#101176)
Docs: Overhaul of PostgreSQL data source documenation (#99908)

* created new topic docs

* added info to config doc

* updates to config doc

* updates to config doc

* finished config doc

* updated Query editor doc

* final edits

* rename, ref URI work

* a few more updates prior to PR issue

* fixed the double Macros heading issue

* final edits and cleanup

* edits based on feedback

* ran prettier

* added updates

* updates based on feedback

* vale linter issues

* more vale linting issues addressed

* small addition on main page

* ran prettier again

* changed title

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/configure/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/configure/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/configure/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/configure/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/configure/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* changed Grafana's

* added changes

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* Update docs/sources/datasources/postgres/query-editor/_index.md

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>

* ran prettier again

* Remove aliases

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Fix link

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Put code in `code`

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Avoid bold for emphasis

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

* Fix link

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>

---------

Signed-off-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Irene Rodríguez <irene.rodriguez@grafana.com>
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
(cherry picked from commit 9780a9c49f)
2025-02-24 08:12:57 -06:00
Matheus Macabu 61fbc0310f [release-11.5.3] Chore: Bump glog in pkg/codegen to v1.2.4 to fix vulnerability (#101141)
Chore: Bump glog in pkg/codegen to v1.2.4 to fix vulnerability (#101126)

Chore: Bump glog pkg/codegen to v1.2.4 to fix vulnerability
(cherry picked from commit 35b218fe10)
2025-02-21 16:09:43 +02:00
grafana-delivery-bot[bot] 6aee3a5c75 [release-11.5.3] IAM: fix grafana_com OAuth connector config overriding (#101070) 2025-02-20 17:44:09 +01:00
grafana-delivery-bot[bot] 5a8f3398bf [release-11.5.3] LBAC: Remove reference for feature toggle (#101082)
Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
2025-02-20 16:53:35 +01:00
Matthew Jacobson 6700924913 [release-11.5.3] Alerting: Fix token-based Slack image upload to work with channel names (#101078)
Alerting: Fix token-based Slack image upload to work with channel names

Upgrades grafana/alerting to be46240 which includes the v11.5 fix.
2025-02-20 10:28:19 -05:00
grafana-delivery-bot[bot] 7905703627 [release-11.5.3] Fix broken links and relfrefs (#101044) 2025-02-20 12:41:15 +02:00
grafana-delivery-bot[bot] 75e6ca56f4 [release-11.5.3] fix broken link (#101038)
Co-authored-by: Irene Rodríguez <irene.rodriguez@grafana.com>
fix broken link (#100967)
2025-02-20 10:45:12 +01:00
grafana-delivery-bot[bot] 9fdf70bf90 [release-11.5.2] Docs: Vale fixes (#100384)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
fixes (#100277)
2025-02-19 16:04:42 -05:00
grafana-delivery-bot[bot] 9e4537fe03 [release-11.5.3] InfluxDB: Improve handling of template variables contained in regular expressions (InfluxQL) (#100977)
InfluxDB: Improve handling of template variables contained in regular expressions (InfluxQL) (#100762)

* Improve handling of template vars in regex

* Review

* Minor update

(cherry picked from commit 8b3047ba1e)

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
2025-02-19 17:09:26 +00:00
grafana-delivery-bot[bot] 68e70b4c5a [release-11.5.2] Auth: Fix AzureAD config UI's ClientAuthentication dropdown (#100869)
Auth: Fix AzureAD config UI's ClientAuthentication dropdown (#100752)

* wip

* Address feedback

(cherry picked from commit 768ec4c2c5)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
2025-02-19 12:33:28 +01:00
grafana-delivery-bot[bot] d732324f53 [release-11.5.3] Alerting docs: fix heading anchor (#100959)
Alerting docs: fix heading anchor (#100783)

Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
(cherry picked from commit 8646961c3f)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-19 12:17:58 +01:00
grafana-delivery-bot[bot] a6fb0f44ba [release-11.5.3] Alerting docs: fix tutorial URL (#100955)
Alerting docs: fix tutorial URL (#100954)

(cherry picked from commit 1fdb36022d)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-19 11:13:32 +01:00
github-actions[bot] 9e942dcb9a Release: 11.5.2 (#100919)
* Update changelog

* Update version to 11.5.2

* baldm0mma/ update version

* baldm0mma/ run yarn

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: jev forsberg <jev.forsberg@grafana.com>
2025-02-18 17:12:07 -07:00
Kevin Minehart f16a6dc98c [release-11.5.2] CI: Post-release process branch / PR migration (#100936)
CI: Post-release process branch / PR migration (#100930)

* update output for token in release-comms

* use token from needs

* generate token in individual workflows

* Set secrets

* define secrest in referenced workflows

* wrong secret lol

* oops

* grafana/grafana -> grafana/grafana-enterprise

(cherry picked from commit 75189de4f7)
2025-02-19 01:53:08 +02:00
grafana-delivery-bot[bot] 25e6d2780b [release-11.5.2] Alerting docs: Update Amazon SNS integration (#100921)
Alerting docs: Update `Amazon SNS` integration (#100754)

* Update `Configure Amazon SNS notifications`

* Clarify templateable fields

* correct prop description

(cherry picked from commit e1c1cc34af)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-18 23:05:26 +01:00
github-actions[bot] 880e5fecb9 apply security patch: release-11.5.2/317-202502130459.patch
commit 4fee27d372e0e4f00a60ecef1d9640bd8165c1c8
Author: AgnesToulet <35176601+AgnesToulet@users.noreply.github.com>
Date:   Tue Feb 11 10:57:05 2025 +0100

    Dashboards: Prevent title longer than 5 000 characters

    (cherry picked from commit f9e0789210004b0bd7902255644ef348ae7b3aa8)
2025-02-18 20:54:59 +00:00
grafana-delivery-bot[bot] 62b5a147fd [release-11.5.2] CI: release comms should trigger on merges to release- branches (#100904)
CI: release comms should trigger on merges to release- branches (#100901)

release comms should trigger on merges to release- branches

(cherry picked from commit 14477a7fe9)

Co-authored-by: Kevin Minehart <5140827+kminehart@users.noreply.github.com>
2025-02-18 22:53:34 +02:00
Matheus Macabu 75890ecc58 [release-11.5.2] Chore: Update alpine docker image (minor) - 3.20.5 to 3.20.6 [security] (#100827)
Chore: Update alpine docker image (minor) - 3.20.5 to 3.20.6 [security] (#100791)

* Chore: Update alpine docker image (minor) - 3.20.5 to 3.20.6 [sec-fixes]

* Chore: Regenerate .drone.yml

---------

Co-authored-by: Matheus Macabu <macabu.matheus@gmail.com>
(cherry picked from commit 27837ee937)

Co-authored-by: Robert Goltz <github@rgoltz.de>
2025-02-18 10:09:58 +01:00
grafana-delivery-bot[bot] 50a0247c22 [release-11.5.2] Update whatsnewURL in package.json (#100756)
Update whatsnewURL in package.json (#100753)

(cherry picked from commit cd30f3839d)

Co-authored-by: Kevin Minehart <5140827+kminehart@users.noreply.github.com>
2025-02-14 20:05:14 +02:00
grafana-delivery-bot[bot] 9908a78c5c [release-11.5.2] Docker: Missing libresolv.so.2 from glibc (#100739)
Docker: Missing libresolv.so.2 from glibc (#100729)

* Docker: Missing libresolv.so.2 from glibc

* Misplaced &&

(cherry picked from commit 3a8a24e662)

Co-authored-by: Kevin Minehart <5140827+kminehart@users.noreply.github.com>
2025-02-14 17:17:00 +02:00
Kevin Minehart 4683c0f157 [release-11.5.2] CI: Backport to release branches (#100691)
CI: Backport to release branches (#100067)

* update backport and release comms

* Backport to release branches and change docs source branch for publishing

* Add new workflows to CODEOWNERS

* Re-add removed line oops

* backport-testing -> grafana

* checkout grafana repo in backport action, reference repo / branch in reusable action

* generate -> create

(cherry picked from commit 6787cdccb9)
2025-02-14 07:56:07 -06:00
grafana-delivery-bot[bot] 72e8b57597 [release-11.5.2] Alerting docs: update Configure Webhook notifications (#100708)
Alerting docs: update `Configure Webhook notifications` (#100650)

* Alerting docs: update `Configure Webhook notifications`

* fix typo

* fix typo

* Update docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>

* Update docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>

* fix typo

* Add `Note` to  configure either HTTP Basic Authentication or the Authorization request header

* Use `inline` format for JSON keys

---------

Co-authored-by: Matthew Jacobson <matthew.jacobson@grafana.com>
(cherry picked from commit f1b4678012)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-14 11:20:14 +01:00
grafana-delivery-bot[bot] b774d0d569 [release-11.5.2] [DOC] Update links, page weights for mounting content in Tempo data source (#100668)
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Kim Nylander <104772500+knylander-grafana@users.noreply.github.com>
2025-02-13 18:40:09 -05:00
grafana-delivery-bot[bot] 0faf11835b [release-11.5.2] Metrics: Use correct gatherer in graphite bridge (#100628)
Metrics: Use correct gatherer in graphite bridge (#100624)

(cherry picked from commit 5a74a1a0f6)

Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com>
2025-02-13 15:30:44 -05:00
Jack Baldry 7776a6c1af Fix publishing workflow (#100657) 2025-02-13 18:30:33 +00:00
grafana-delivery-bot[bot] 6c3e9e5976 [release-11.5.2] IAM: log error when malformed json arrays are found in SSO configs (#100649)
IAM: Log error when malformed json arrays are found in SSO configs (#99896)

(cherry picked from commit eeadb7e771)
2025-02-13 18:37:38 +01:00
grafana-delivery-bot[bot] 327ca47f51 [release-11.5.2] Dashboards: Fix repeats not being added on refresh when using searchLayout (#100632)
Dashboards: Fix repeats not being added on refresh when using searchLayout (#100621)

Fix repeats not being added

(cherry picked from commit 1018aec6bc)

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
2025-02-13 18:50:05 +02:00
Dominik Prokop a957c28316 [release-11.5.2] Dashboards: Bring back scripted dashboards (#100633)
Dashboards: Bring back scripted dashboards (#100575)

* Dashboards: Bring back scripted dashboards

* Fix scripted dashboard examples

* Fix dashboard-solo page not respecnig scripted dashboards

(cherry picked from commit 7edcde6365)
2025-02-13 17:48:45 +01:00
grafana-delivery-bot[bot] b321585bde [release-11.5.2] Docs: Improve instructions to change basic roles (#100637)
Co-authored-by: Hugo Kiyodi Oshiro <hugo.oshiro@grafana.com>
2025-02-13 17:58:13 +02:00
grafana-delivery-bot[bot] cfa529295f [release-11.5.2] Docs: Fix URLs to auth providers from Team Sync page (#100620)
Co-authored-by: Victor Cinaglia <victor@grafana.com>
Fix URLs to auth providers from Team Sync page (#100563)
2025-02-13 15:41:34 +01:00
grafana-delivery-bot[bot] 3881a173fe [release-11.5.2] AuthN: Refetch user on "ErrUserAlreadyExists" (#100582)
AuthN: Refetch user on "ErrUserAlreadyExists" (#100346)

* AuthN: Refetch user on "ErrUserAlreadyExists"

(cherry picked from commit 0b4c622df8)

Co-authored-by: Karl Persson <23356117+kalleep@users.noreply.github.com>
2025-02-13 12:03:29 +01:00
grafana-delivery-bot[bot] 5533f62a71 [release-11.5.2] Auth: Add early return if auth_token is in the URL for JWT auth (#100574)
Auth: Add early return if `auth_token` is in the URL for JWT auth (#100539)

* Add early return

* Update public/app/app.ts

Co-authored-by: Victor Cinaglia <victor@grafana.com>

---------

Co-authored-by: Victor Cinaglia <victor@grafana.com>
(cherry picked from commit 5a6d2f2e49)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
2025-02-13 11:28:21 +01:00
grafana-delivery-bot[bot] 49a32d71be [release-11.5.2] Docs: updated supported versions with 11.5 (#100557)
Co-authored-by: Isabel Matwawana <isabel.matwawana@grafana.com>
Co-authored-by: margotphelps <123196595+margotphelps@users.noreply.github.com>
2025-02-12 16:20:32 -05:00
grafana-delivery-bot[bot] d3cab8217f [release-11.5.2] Auth: Fix redirect with JWT auth URL login (#100355)
Auth: Fix redirect with JWT auth URL login (#100295)

fix

(cherry picked from commit acc1521929)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
2025-02-12 20:37:03 +02:00
grafana-delivery-bot[bot] e8887275ae [release-11.5.2] CI: Add release branches to patch automation (#100527)
CI: Add release branches to patch automation (#100442)

* CI: Add release branches to patch automation

* Update .github/workflows/create-security-patch-from-security-mirror.yml

Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>

---------

Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>
(cherry picked from commit a8b98ded66)

Co-authored-by: Kevin Minehart <5140827+kminehart@users.noreply.github.com>
2025-02-12 18:21:07 +02:00
Josh Hunt b8d8a94ebc [release-11.5.2] Chore: pin tonistiigi/binfmt version (#100518)
Chore: pin tonistiigi/binfmt version (#100510)

* Chore: pin tonistiigi/binfmt version

* change version to qemu-v7.0.0-28

* uninstall first, log version

* uninstall first, log version

* uninstall first, log version

(cherry picked from commit a9b4b1e5be)
2025-02-12 16:03:10 +00:00
grafana-delivery-bot[bot] c30b9bd0bb [release-11.5.2] Alerting docs: remove admonition about auto-generated policies (#100514)
Alerting docs: remove admonition about auto-generated policies (#100501)

(cherry picked from commit 983829e47b)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-12 15:22:49 +01:00
Moustafa Baiou fb0d6be79e Alerting: Allow specifying uid for new rules added to groups (#99858)
When modifying rule groups the `uid` can be specified but only if the rule already existed in the DB. If the rule is new the update would be rejected.

This updates the RuleGroup provisioning apis to allow specifying the `uid` when creating/updating rule groups.

Additionally, the RuleGroupIdx was not being updated when rules were reordered in the group.

Context: https://github.com/grafana/terraform-provider-grafana/pull/1971#issuecomment-2599223897
Relates to: https://github.com/grafana/terraform-provider-grafana/issues/1928

Fixes: #98283
(cherry picked from commit 7dee4d1808)
2025-02-12 09:10:39 -05:00
Yuri Tseretyan 2728e5cf14 Alerting: Refactor integration tests (#99519)
---------

Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
(cherry picked from commit af663dadc7)
2025-02-12 09:10:39 -05:00
grafana-delivery-bot[bot] 822e5fb1a1 [release-11.5.2] docs: Copy code to clipboard (set-up-https.md) (#100512)
Co-authored-by: Solomon Himelbloom <7608183+TechSolomon@users.noreply.github.com>
2025-02-12 15:48:15 +02:00
Pepe Cano f433b8c240 [release-11.5.2] Update Intro > Queries and Conditions (#100490)
Update `Intro > Queries and Conditions` (#95109) * Update `Intro > Queries and Conditions`
* Small tweaks (advanced options) and screenshots

* Change `Expressions` heading

* Set links from Alert rules introduction

* Minor intro changes

* small change due to recent updates

* fix vale errors

* fix vale error

* Remove unnecessary mention to `alertingQueryAndExpressionsStepMode` feature flag

(cherry picked from commit 99c8d4b0c6)
2025-02-12 12:02:25 +01:00
grafana-delivery-bot[bot] 676599ad7a [release-11.5.2] Alerting docs: Add Enable notifications section to Configure contact points docs (#100493)
Alerting docs: Add `Enable notifications` section to `Configure contact points` docs (#100446)

Alerting docs: Add `Enable notifications` section to `Configure contact points` page

(cherry picked from commit 8e436fc473)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-12 12:01:41 +01:00
grafana-delivery-bot[bot] 34cdea5bb5 [release-11.5.2] Alerting docs: clarify that silences and mute timings do not interrupt alert evaluation (#100491)
Alerting docs: clarify that `silences` and `mute timings` do not interrupt alert evaluation (#100414)

* Alerting docs: clarify that `silences` and `mute timings` do not interrupt alert evaluation

* replace `ad-hoc` word

(cherry picked from commit 2b4e1f3c51)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-12 11:29:36 +01:00
grafana-delivery-bot[bot] b857272fa2 [release-11.5.2] Fix: Optimise frontend Postgresql plugin cache busting (#100411)
Fix: Optimise frontend Postgresql plugin cache busting (#100406)

fix(postgresql): add version for optimised cache busting

(cherry picked from commit cbe5741096)

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
2025-02-11 15:34:49 +01:00
grafana-delivery-bot[bot] 6d67738b5f [release-11.5.2] Docs: Fixed hyperlinks pointing to supported auth providers (#100408)
Co-authored-by: Vishal N <dev@vishalnandagopal.com>
Fixed hyperlinks pointing to supported auth providers (#100404)
2025-02-11 12:46:55 +02:00
grafana-delivery-bot[bot] f73c2fdf7a [release-11.5.2] grafana-ui: Update InlineField error prop type to React.ReactNode (#100373)
grafana-ui: Update InlineField error prop type to React.ReactNode (#100347)

(cherry picked from commit 2518012569)

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
2025-02-10 18:17:07 +02:00
Josh Hunt 100c91ca14 [release-11.5.2] Chore: Remove unused knip dependency (#100358)
manually implement change from PR #100351 for backporting
2025-02-10 15:06:37 +01:00
Jev Forsberg 7beb0a1ff6 [release-11.5.2] Chore: Update grabpl version to v3.1.2 (#100243)
Chore: Update grabpl version to v3.1.2 (#100157)

baldm0mma/ update grabpl version

(cherry picked from commit 8e3327a446)
2025-02-07 08:29:30 -07:00
grafana-delivery-bot[bot] 9bdd480326 [release-11.5.2] Docs: adding actions_allow_post_url example to plugin docs (#100203)
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
2025-02-07 08:55:58 -06:00
grafana-delivery-bot[bot] 273a9b17c9 [release-11.5.2] Share: Fix short links when root_url is different from the browser URL (#100202)
Share: Fix short links when root_url is different from the browser URL (#99950)

Share: Fix short links when appUrl is misconfigured
(cherry picked from commit cd7c9f8666)

Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>
2025-02-07 10:53:10 +01:00
grafana-delivery-bot[bot] b11b012240 [release-11.5.2] CloudMigrations: save snapshot of alert rule groups (#100184)
CloudMigrations: save snapshot of alert rule groups (#100109)

(cherry picked from commit fde475e3d9)

Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com>
2025-02-07 10:50:52 +01:00
grafana-delivery-bot[bot] 234d3d16e4 [release-11.5.2] Loki query direction: run initialization only in Explore and Dashboards (#100192)
Loki query direction: run initialization only in Explore and Dashboards (#100182)

(cherry picked from commit 4e6bdce41c)

Co-authored-by: Matias Chomicki <matyax@gmail.com>
2025-02-06 14:51:57 +01:00
grafana-delivery-bot[bot] ed62b50def [v11.5.x] Docs: move missing ref URI to correct page (#100134)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-02-05 12:16:37 -05:00
grafana-delivery-bot[bot] 967a5d3fc3 [v11.5.x] RBAC: Don't check folder access if annotationPermissionUpdate FT is enabled (#100117)
RBAC: Don't check folder access if `annotationPermissionUpdate` FT is enabled (#99717)

don't check folder access if annotation permission update is enabled

(cherry picked from commit 095593c018)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2025-02-05 13:36:15 +02:00
grafana-delivery-bot[bot] 6b4c70d6a3 [v11.5.x] Chore: Update alpine build docker image (#100018)
Chore: Update alpine build docker image (#99998)

baldm0mma/ update alpine build image

(cherry picked from commit 46af49f907)

Co-authored-by: Jev Forsberg <46619047+baldm0mma@users.noreply.github.com>
2025-02-04 14:33:29 -07:00
grafana-delivery-bot[bot] d75d140554 [v11.5.x] Plugin Metrics: Eliminate data race in plugin metrics middleware (#100078)
Plugin Metrics: Eliminate data race in plugin metrics middleware (#99396)

fix: eliminate data race in plugin metrics middleware

A data race was detected when multiple goroutines accessed the `MetricsMiddleware`
simultaneously. The race occurred because a single `MetricsMiddleware` instance
was being shared across goroutines while its `BaseHandler` field was being
modified during middleware chain setup.

Fix by creating a new `MetricsMiddleware` instance for each middleware chain,
while safely sharing the thread-safe Prometheus metrics and plugin registry.
This maintains proper metrics collection while eliminating the mutable shared
state that caused the race condition.

Original error was detected here:

```
WARNING: DATA RACE
Read at 0x00c0039c0790 by goroutine 4486:
  github.com/grafana/grafana-plugin-sdk-go/backend.(*ErrorSourceMiddleware).CallResource()
      /Users/clord/src/grafana/irm-devstack/.devenv/state/go/pkg/mod/github.com/grafana/grafana-plugin-sdk-go@v0.261.0/backend/error_source_middleware.go:93 +0x40
  github.com/grafana/grafana-plugin-sdk-go/backend.BaseHandler.CallResource()
  ...

```

(cherry picked from commit e74cf72d99)

Co-authored-by: Christopher Lord <christopher.lord@grafana.com>
2025-02-04 20:08:52 +02:00
grafana-delivery-bot[bot] cbfb776273 [v11.5.x] Docs: fix link text (#100052)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
fix link text (#99932)
2025-02-04 09:39:14 -05:00
grafana-delivery-bot[bot] b45af3e8a0 [v11.5.x] DashboardList: Throttle the re-renders (#100046) 2025-02-04 14:34:21 +02:00
grafana-delivery-bot[bot] 9c48b9420a [v11.5.x] Alerting docs: update screenshot (modify NoData/Error state) (#100015)
Alerting docs: update screenshot (modify NoData/Error state) (#99996)

(cherry picked from commit 5fe6479a10)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-02-03 22:13:57 +01:00
github-actions[bot] e0aadb4dab Release: 11.5.1 (#99957)
* Update changelog

* Update version to 11.5.1

* manually bump dep @grafana/plugin-configs

* update changelog manually

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: joshhunt <josh@trtr.co>
2025-02-03 13:23:09 +00:00
grafana-delivery-bot[bot] eb2b19186c [v11.5.x] Docs: Updated Reporting docs (#99931)
Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-01-31 17:22:52 -05:00
grafana-delivery-bot[bot] 6d9d0d7748 [v11.5.x] Docker: Use our own glibc 2.40 binaries (#99918)
Docker: Use our own glibc 2.40 binaries (#99903)

* use our own glibc 2.40 binaries

(cherry picked from commit 481f99b07f)

Co-authored-by: Dan Cech <dcech@grafana.com>
2025-01-31 14:36:09 -05:00
grafana-delivery-bot[bot] 6cc10d30df [v11.5.x] Docs: Fix broken link (#99909)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
Fix broken link (#99907)
2025-01-31 12:05:14 -05:00
grafana-delivery-bot[bot] 5acb12be61 [v11.5.x] Alerting: Call RLock() before reading sendAlertsTo map (#99880)
Alerting: Call RLock() before reading sendAlertsTo map (#99812)

* Alerting: Call RLock() before reading sendAlertsTo map

* defer unlocking

* drive-tru fix for another lock

* less time holding the lock in SyncAndApplyConfigFromDatabase

(cherry picked from commit 39f212a965)

Co-authored-by: Santiago <santiagohernandez.1997@gmail.com>
2025-01-31 14:45:51 +01:00
grafana-delivery-bot[bot] 7617fa1d1f [v11.5.x] TransformationFilter: Include transformation outputs in transformation filtering options (#99878)
TransformationFilter: Include transformation outputs in transformation filtering options (#98323)

* wip: include transformation output as filtering option

* add refId to joinByField transformation

* clean up

* add refId to transformations that create new data frames

* adjust duplicate query removal for filtering options

* refactor transformation input/output subscription effect

* adjust input data frame filtering logic to include transformations as input for debug view

* transformation filter can only filter on output of previous transformation

(cherry picked from commit a32eed1d13)

Co-authored-by: Sergej-Vlasov <37613182+Sergej-Vlasov@users.noreply.github.com>
2025-01-31 11:49:21 +00:00
grafana-delivery-bot[bot] d788e8d44e [v11.5.x] CodeEditor: Fix cursor alignment (#99863)
CodeEditor: Fix cursor alignment (#99090)

* remeasure fonts once they've loaded

* add test mock

* fix unit test

* remeasure fonts after the editor has mounted just to be safe

(cherry picked from commit 8e59f618c1)

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
2025-01-31 11:46:08 +02:00
Yuri Tseretyan 9c7139ee7a [v11.5.x] Alerting: k8s receivers api encrypt existing unencrypted secureFields on update (#99847)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 16:42:33 -07:00
grafana-delivery-bot[bot] 86194faffd [v11.5.x] Docs: Moving migrate to cloud guide from website repo to OSS (#99839)
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
2025-01-30 20:35:58 +02:00
grafana-delivery-bot[bot] 70f5e59d94 [v11.5.x] Update make docs procedure (#99836)
Co-authored-by: grafanabot <bot@grafana.com>
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-30 17:29:07 +00:00
grafana-delivery-bot[bot] b547440a1e [v11.5.x] Remove old admonition (#99827)
Co-authored-by: Irene Rodríguez <irene.rodriguez@grafana.com>
2025-01-30 18:31:42 +02:00
grafana-delivery-bot[bot] 5400abfac2 [v11.5.x] DashboardScenes: Fix issue where relative time does not pass properly (#99794)
DashboardScenes: Fix issue where relative time does not pass properly (#99282)

fix issue where relative time does not pass properly

(cherry picked from commit bf1a0837af)

Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com>
2025-01-30 10:48:31 +00:00
grafana-delivery-bot[bot] 148fd6fa7c [v11.5.x] [DOC] Add connection URL info to Pyroscope datasource doc (#99707)
Co-authored-by: Kim Nylander <104772500+knylander-grafana@users.noreply.github.com>
Co-authored-by: Aleksandar Petrov <8142643+aleks-p@users.noreply.github.com>
2025-01-29 13:42:08 -05:00
grafana-delivery-bot[bot] 51f2ae7936 [v11.5.x] Docs: add pan and zoom key combos (#99711)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-01-29 09:16:06 -05:00
grafana-delivery-bot[bot] 86fcf80315 [v11.5.x] Azure: Correctly set application insights resource values (#99599)
* Azure: Correctly set application insights resource values (#99214)

Correctly set resource values

(cherry picked from commit 30ee8b9813)

* Fix test

---------

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
2025-01-28 18:57:47 +00:00
github-actions[bot] c055d03d00 Release: 11.5.0 (#99653)
* Update changelog

* Update version to 11.5.0

* adjust version of plugin-configs

* baldm0mma/update changelog content

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
Co-authored-by: jev forsberg <jev.forsberg@grafana.com>
2025-01-28 11:40:01 -07:00
grafana-delivery-bot[bot] 85379b8f2d [v11.5.x] Docs: What's new & Upgrade guide v11.5 (#99676)
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Robby Milo <robbymilo@fastmail.com>
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
Co-authored-by: Isabel Matwawana <isabel.matwawana@grafana.com>
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
2025-01-28 17:53:33 +02:00
grafana-delivery-bot[bot] df7987a6b8 [v11.5.x] docs: Fixes broken link in data source LBAC (#99497)
Co-authored-by: Irene Rodríguez <irene.rodriguez@grafana.com>
Co-authored-by: Alex Bikfalvi <alex@bikfalvi.com>
Fixes broken link in data source LBAC (#99496)
2025-01-24 13:31:53 +02:00
Jack Baldry 56e82b7a1c [v11.5.x] Remove codespell (#99428) 2025-01-23 12:41:36 +00:00
grafana-delivery-bot[bot] 41e7cd2c02 [v11.5.x] LibraryPanel: Fallback to panel title if library panel title is not set (#99411)
LibraryPanel: Fallback to panel title if library panel title is not set (#99377)

(cherry picked from commit c862aa4d68)

Co-authored-by: Ivan Ortega Alba <ivanortegaalba@gmail.com>
2025-01-23 11:09:54 +02:00
grafana-delivery-bot[bot] 6167aac263 [v11.5.x] Docs: add user de-duplication description, update usage billing instructions (#99407)
Co-authored-by: Irene Rodríguez <irene.rodriguez@grafana.com>
Co-authored-by: Mitch Seaman <mjseaman@users.noreply.github.com>
2025-01-23 09:56:45 +02:00
grafana-delivery-bot[bot] 6ee1bfb736 [v11.5.x] docs>alert-rules>templates:example-fix (#99361)
docs>alert-rules>templates:example-fix (#99355)

* docs>alert-rules>templates:example-fix

* second-fix

* fixed 2 other label templates

(cherry picked from commit 88d5ae8153)

Co-authored-by: antonio <45235678+tonypowa@users.noreply.github.com>
2025-01-22 13:20:12 +02:00
grafana-delivery-bot[bot] e0d8318caa [v11.5.x] Alerting docs: add Admonitions to Link Doc pages with practical Tutorials (#99324)
Alerting docs: add Admonitions to Link Doc pages with practical Tutorials (#99317)

Alerting docs: add admonitions to link to practical tutorials

(cherry picked from commit c7edbffd82)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-01-21 15:31:25 +01:00
grafana-delivery-bot[bot] 842179916d [v11.5.x] Alerting docs: add instructions to execute notification template examples (#99304)
Alerting docs: add instructions to execute notification template examples (#99275)

(cherry picked from commit 9ce9ad1777)

Co-authored-by: Pepe Cano <825430+ppcano@users.noreply.github.com>
2025-01-21 10:49:22 +01:00
grafana-delivery-bot[bot] d7d80d2634 [v11.5.x] Docs: Reporting restructure (#99289)
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-01-20 14:32:03 -05:00
grafana-delivery-bot[bot] fb0204c8df [v11.5.x] Azure: Improve resource request error handling (#99259)
Azure: Improve resource request error handling (#99017)

* Improve resource request error handling

- Correctly parse JSON responses
- Log erroneous failures in JSON marshalling/unmarshalling
- Correctly set response status code
- Do not attempt to use the response writer as it will be nil

* Minor change

* Improve type assertion handling

(cherry picked from commit f6194931f5)

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
2025-01-20 15:17:04 +02:00
grafana-delivery-bot[bot] 5f7f04518b [v11.5.x] Add Apache instructions (#99211)
Co-authored-by: Joseph Perez <45749060+josmperez@users.noreply.github.com>
Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
Co-authored-by: Irene Rodriguez <irene.rodriguez@grafana.com>
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
Co-authored-by: Ronald McCollam <mccollam@gmail.com>
2025-01-17 12:11:50 -06:00
grafana-delivery-bot[bot] 5e369c6709 [v11.5.x] Docs: move DynamoDB to Unsupported list (#99195)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-01-17 10:05:55 -05:00
Mariell Hoversholm 940d71250b Security: Update to Go 1.23.5 - Backport to v11.5.x (#99122)
* feat: update to Go 1.23.5

* chore: make drone

* chore: make update-workspace

* fix: 1.23.5, not 1.23.4

* fix: update in Makefile

* CI: Force re-build
2025-01-17 09:30:36 +01:00
2880 changed files with 50469 additions and 114609 deletions
-4
View File
@@ -86,10 +86,6 @@ module.exports = [
importNames: ['Layout', 'HorizontalGroup', 'VerticalGroup'],
message: 'Use Stack component instead.',
},
{
group: ['@grafana/ui/src/*', '@grafana/runtime/src/*', '@grafana/data/src/*'],
message: 'Import from the public export instead.',
},
],
},
],
+484 -986
View File
File diff suppressed because it is too large Load Diff
-11
View File
@@ -5,10 +5,6 @@ GOPATH ?= $(shell go env GOPATH)
GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin
GO ?= $(shell which go)
# Add this near the top of the file, after the initial variable definitions
ifndef VARIABLES_MK
VARIABLES_MK := 1
# Below generated variables ensure that every time a tool under each variable is invoked, the correct version
# will be used; reinstalling only if needed.
# For example for bra variable:
@@ -27,12 +23,6 @@ $(BRA): $(BINGO_DIR)/bra.mod
@echo "(re)installing $(GOBIN)/bra-v0.0.0-20200517080246-1e3013ecaff8"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=bra.mod -o=$(GOBIN)/bra-v0.0.0-20200517080246-1e3013ecaff8 "github.com/unknwon/bra"
COG := $(GOBIN)/cog-v0.0.15
$(COG): $(BINGO_DIR)/cog.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@echo "(re)installing $(GOBIN)/cog-v0.0.15"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=cog.mod -o=$(GOBIN)/cog-v0.0.15 "github.com/grafana/cog/cmd/cli"
CUE := $(GOBIN)/cue-v0.5.0
$(CUE): $(BINGO_DIR)/cue.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@@ -69,4 +59,3 @@ $(SWAGGER): $(BINGO_DIR)/swagger.mod
@echo "(re)installing $(GOBIN)/swagger-v0.30.6-0.20240310114303-db51e79a0e37"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=swagger.mod -o=$(GOBIN)/swagger-v0.30.6-0.20240310114303-db51e79a0e37 "github.com/go-swagger/go-swagger/cmd/swagger"
endif
-5
View File
@@ -1,5 +0,0 @@
module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT
go 1.23.4
require github.com/grafana/cog v0.0.15 // cmd/cli
-2
View File
@@ -10,8 +10,6 @@ fi
BRA="${GOBIN}/bra-v0.0.0-20200517080246-1e3013ecaff8"
COG="${GOBIN}/cog-v0.0.15"
CUE="${GOBIN}/cue-v0.5.0"
DRONE="${GOBIN}/drone-v1.5.0"
+143 -220
View File
File diff suppressed because it is too large Load Diff
+20 -31
View File
@@ -32,13 +32,13 @@
/devenv/README.md @grafana/docs-grafana
# START Technical documentation
/.vale.ini @grafana/docs-tooling
# `make docs` procedure and related workflows are owned @grafana/docs-tooling. Slack #docs.
/docs/ @grafana/docs-tooling
/docs/.codespellignore @grafana/docs-tooling
/docs/sources/ @irenerl24
/docs/sources/alerting/ @JohnnyK-Grafana
/docs/sources/alerting/ @brendamuir
/docs/sources/dashboards/ @imatwawana
/docs/sources/datasources/ @lwandz13
/docs/sources/panels-visualizations/ @imatwawana
@@ -66,13 +66,9 @@
/scripts/go-workspace @grafana/grafana-app-platform-squad
/hack/ @grafana/grafana-app-platform-squad
/pkg/apis/provisioning @grafana/grafana-git-ui-sync-team
/pkg/registry/apis/provisioning @grafana/grafana-git-ui-sync-team
/apps/alerting/ @grafana/alerting-backend
/apps/alerting/ @grafana/alerting-backend @grafana/alerting-frontend
/apps/playlist/ @grafana/grafana-app-platform-squad
/apps/investigations/ @fcjack @matryer @svennergr
/apps/advisor/ @grafana/plugins-platform-backend
/apps/investigation/ @fcjack @matryer
/pkg/api/ @grafana/grafana-backend-group
/pkg/apis/ @grafana/grafana-app-platform-squad
/pkg/apis/query @grafana/grafana-datasources-core-services
@@ -241,7 +237,6 @@
/devenv/dev-dashboards/extensions/ @grafana/plugins-platform-frontend
/devenv/docker/blocks/alert_webhook_listener/ @grafana/alerting-backend
/devenv/docker/blocks/stateful_webhook/ @grafana/alerting-backend
/devenv/docker/blocks/caddy_tls/ @grafana/alerting-backend
/devenv/docker/blocks/clickhouse/ @grafana/partner-datasources
/devenv/docker/blocks/collectd/ @grafana/observability-metrics
@@ -381,11 +376,6 @@
/crowdin.yml @grafana/grafana-frontend-platform
/public/locales/ @grafana/grafana-frontend-platform
/public/locales/de-DE @grafanabot
/public/locales/es-ES @grafanabot
/public/locales/fr-FR @grafanabot
/public/locales/pt-BR @grafanabot
/public/locales/zh-Hans @grafanabot
/public/app/core/internationalization/ @grafana/grafana-frontend-platform
/e2e/ @grafana/grafana-frontend-platform
/e2e/cloud-plugins-suite/ @grafana/partner-datasources
@@ -411,7 +401,7 @@
/packages/grafana-schema/src/**/*canvas* @grafana/dataviz-squad
/packages/grafana-schema/src/**/*tempo* @grafana/observability-traces-and-profiling
/packages/grafana-sql/ @grafana/partner-datasources @grafana/oss-big-tent
/packages/grafana-ui/.storybook/ @grafana/grafana-frontend-platform
/packages/grafana-ui/.storybook/ @grafana/plugins-platform-frontend
/packages/grafana-ui/src/components/ @grafana/grafana-frontend-platform
/packages/grafana-ui/src/components/BarGauge/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/DataLinks/ @grafana/dataviz-squad
@@ -430,7 +420,9 @@
/packages/grafana-ui/src/graveyard/Graph/ @grafana/dataviz-squad
/packages/grafana-ui/src/graveyard/GraphNG/ @grafana/dataviz-squad
/packages/grafana-ui/src/graveyard/TimeSeries/ @grafana/dataviz-squad
/packages/grafana-ui/src/utils/storybook/ @grafana/grafana-frontend-platform
/packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend
/plugins-bundled/ @grafana/plugins-platform-frontend
# root files, mostly frontend
/.browserslistrc @grafana/frontend-ops
@@ -444,7 +436,6 @@
/.betterer.eslint.config.js @grafana/frontend-ops
/.gitattributes @grafana/frontend-ops
/.gitignore @grafana/frontend-ops
/.ignore @grafana/frontend-ops
/.nvmrc @grafana/frontend-ops
/.prettierignore @grafana/frontend-ops
/.yarn @grafana/frontend-ops
@@ -465,7 +456,6 @@
playwright.config.ts @grafana/plugins-platform-frontend
# public folder
/public/app/api/ @grafana/grafana-frontend-platform
/public/app/core/ @grafana/grafana-frontend-platform
/public/app/core/components/TimePicker/ @grafana/grafana-frontend-platform
/public/app/core/components/Layers/ @grafana/dataviz-squad
@@ -502,7 +492,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/explore/ @grafana/observability-traces-and-profiling
/public/app/features/expressions/ @grafana/observability-metrics
/public/app/features/folders/ @grafana/grafana-frontend-platform
/public/app/features/iam/ @grafana/grafana-frontend-platform
/public/app/features/inspector/ @grafana/dashboards-squad
/public/app/features/invites/ @grafana/grafana-frontend-platform
/public/app/features/library-panels/ @grafana/dashboards-squad
@@ -516,6 +505,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/playlist/ @grafana/dashboards-squad
/public/app/features/plugins/ @grafana/plugins-platform-frontend
/public/app/features/profile/ @grafana/grafana-frontend-platform
/public/app/features/query-library/ @grafana/grafana-frontend-platform
/public/app/features/runtime/ @ryantxu
/public/app/features/query/ @grafana/dashboards-squad
/public/app/features/sandbox/ @grafana/grafana-frontend-platform
@@ -544,7 +534,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/plugins/panel/heatmap/ @grafana/dataviz-squad
/public/app/plugins/panel/histogram/ @grafana/dataviz-squad
/public/app/plugins/panel/logs/ @grafana/observability-logs
/public/app/plugins/panel/logs-new/ @grafana/observability-logs
/public/app/plugins/panel/nodeGraph/ @grafana/observability-traces-and-profiling @grafana/app-o11y-visualizations
/public/app/plugins/panel/traces/ @grafana/observability-traces-and-profiling
/public/app/plugins/panel/flamegraph/ @grafana/observability-traces-and-profiling
@@ -593,7 +582,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/explore/NodeGraph/ @grafana/observability-traces-and-profiling
/public/app/features/explore/FlameGraph/ @grafana/observability-traces-and-profiling
/public/app/features/explore/TraceView/ @grafana/observability-traces-and-profiling
/public/app/features/explore/QueryLibrary/ @grafana/grafana-frontend-platform
/public/api-merged.json @grafana/grafana-backend-group
/public/api-enterprise-spec.json @grafana/grafana-backend-group
@@ -606,6 +594,9 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/AppWrapper.tsx @grafana/frontend-ops
/public/app/partials/ @grafana/grafana-frontend-platform
/scripts/benchmark-access-control.sh @grafana/access-squad
/scripts/check-breaking-changes.sh @grafana/plugins-platform-frontend
/scripts/ci-* @grafana/grafana-developer-enablement-squad
@@ -630,7 +621,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/scripts/cleanup-husky.sh @grafana/frontend-ops
/scripts/verify-repo-update/ @grafana/grafana-developer-enablement-squad
/scripts/generate-rtk-apis.ts @grafana/grafana-frontend-platform
/scripts/process-specs.ts @grafana/grafana-frontend-platform
/scripts/generate-alerting-rtk-apis.ts @grafana/alerting-frontend
/scripts/levitate-parse-json-report.js @grafana/plugins-platform-frontend
/scripts/levitate-show-affected-plugins.js @grafana/plugins-platform-frontend
@@ -644,6 +634,9 @@ playwright.config.ts @grafana/plugins-platform-frontend
.betterer.results @grafanabot
.betterer.ts @grafana/grafana-frontend-platform
# @grafana/ui component documentation
*.mdx @grafana/plugins-platform-frontend
# Design system
/public/img/icons/unicons/ @grafana/design-system
@@ -734,7 +727,6 @@ embed.go @grafana/grafana-as-code
/pkg/registry/apis/alerting @grafana/grafana-app-platform-squad @grafana/alerting-backend
/pkg/registry/apis/query @grafana/grafana-datasources-core-services
/pkg/registry/apis/userstorage @grafana/grafana-app-platform-squad @grafana/plugins-platform-backend
/pkg/registry/apps/advisor @grafana/plugins-platform-backend
/pkg/codegen/ @grafana/grafana-as-code
/pkg/codegen/generators @grafana/grafana-as-code
/pkg/kinds/*/*_gen.go @grafana/grafana-as-code
@@ -754,7 +746,6 @@ embed.go @grafana/grafana-as-code
/.github/pr-checks.json @tolzhabayev
/.github/pr-commands.json @tolzhabayev
/.github/renovate.json5 @grafana/frontend-ops
/.github/workflows/add-to-whats-new.yml @grafana/docs-tooling
/.github/workflows/auto-triager/ @grafana/plugins-platform-frontend
/.github/workflows/alerting-swagger-gen.yml @grafana/alerting-backend
/.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad
@@ -770,7 +761,6 @@ embed.go @grafana/grafana-as-code
/.github/workflows/commands.yml @torkelo
/.github/workflows/community-release.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/detect-breaking-changes-* @grafana/plugins-platform-frontend
/.github/workflows/documentation-ci.yml @grafana/docs-tooling
/.github/workflows/doc-validator.yml @grafana/docs-tooling
/.github/workflows/deploy-pr-preview.yml @grafana/docs-tooling
/.github/workflows/epic-add-to-platform-ux-parent-project.yml @meanmina
@@ -788,16 +778,16 @@ embed.go @grafana/grafana-as-code
/.github/workflows/publish-technical-documentation-next.yml @grafana/docs-tooling
/.github/workflows/publish-technical-documentation-release.yml @grafana/docs-tooling
/.github/workflows/remove-milestone.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/sbom-report.yml @grafana/security-team
/.github/workflows/scripts/json-file-to-job-output.js @grafana/plugins-platform-frontend
/.github/workflows/stale.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/update-changelog.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/update-make-docs.yml @grafana/docs-tooling
/.github/workflows/scripts/kinds/verify-kinds.go @grafana/platform-monitoring
/.github/workflows/publish-kinds-next.yml @grafana/platform-monitoring
/.github/workflows/publish-kinds-release.yml @grafana/platform-monitoring
/.github/workflows/verify-kinds.yml @grafana/platform-monitoring
/.github/workflows/scripts/kinds/verify-kinds.go @grafana/platform-cat
/.github/workflows/publish-kinds-next.yml @grafana/platform-cat
/.github/workflows/publish-kinds-release.yml @grafana/platform-cat
/.github/workflows/verify-kinds.yml @grafana/platform-cat
/.github/workflows/dashboards-issue-add-label.yml @grafana/dashboards-squad
/.github/workflows/run-schema-v2-e2e.yml @grafana/dashboards-squad
/.github/workflows/ephemeral-instances-pr-comment.yml @grafana/grafana-backend-services-squad
/.github/workflows/create-security-patch-from-security-mirror.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/core-plugins-build-and-release.yml @grafana/plugins-platform-frontend @grafana/plugins-platform-backend
@@ -806,7 +796,6 @@ embed.go @grafana/grafana-as-code
/.github/workflows/pr-go-workspace-check.yml @grafana/grafana-app-platform-squad
/.github/workflows/pr-dependabot-update-go-workspace.yml @grafana/grafana-app-platform-squad
/.github/workflows/pr-k8s-codegen-check.yml @grafana/grafana-app-platform-squad
/.github/workflows/go-lint.yml @grafana/grafana-backend-services-squad
/.github/workflows/trivy-scan.yml @grafana/grafana-backend-services-squad
/.github/workflows/changelog.yml @zserge
/.github/workflows/actions/changelog @zserge
+1 -1
View File
@@ -8,7 +8,7 @@ updates:
directories:
- "/"
- "/apps/playlist"
- "/apps/investigations"
- "/apps/investigation"
- "/pkg/aggregator"
- "/pkg/apimachinery"
- "/pkg/apiserver"
+3 -3
View File
@@ -14,6 +14,7 @@
"public/**/*",
"packages/**/*",
"e2e/**/*",
"plugins-bundled/**/*",
"scripts/build/release-packages.sh",
"scripts/circle-release-next-packages.sh",
"scripts/ci-frontend-metrics.sh",
@@ -247,8 +248,7 @@
"/pkg/services/sqlstore/migrations/ualert/**/*",
"/pkg/services/alerting/**/*",
"/public/app/features/alerting/**/*",
"/pkg/tests/api/alerting/**/*",
"/pkg/tests/alertmanager/**/*"
"/pkg/tests/api/alerting/**/*"
],
"action": "updateLabel",
"addLabel": "area/alerting"
@@ -437,4 +437,4 @@
"action": "updateLabel",
"addLabel": "area/panel/table"
}
]
]
+2 -1
View File
@@ -13,12 +13,13 @@
"slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
"@types/slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
"@types/slate", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
"storybook-dark-mode", // 4.0.2 causes storybook 8.4 to break with react hooks errors
// Temporarily pause updating lerna and nx until we resolve build issues
"lerna",
"nx"
],
includePaths: ["package.json", "packages/**", "public/app/plugins/**"],
ignorePaths: ["emails/**", "**/mocks/**"],
ignorePaths: ["emails/**", "plugins-bundled/**", "**/mocks/**"],
labels: ["area/frontend", "dependencies", "no-changelog"],
postUpdateOptions: ["yarnDedupeHighest"],
packageRules: [
+20 -26
View File
@@ -69,17 +69,8 @@ const graphql = async (ghtoken, query, variables) => {
},
body: JSON.stringify({ query, variables }),
});
const res = await results.json();
LOG(
JSON.stringify({
status: results.status,
text: results.statusText,
})
);
return res.data;
const { data } = await results.json();
return data;
};
// Using Github GraphQL API find the timestamp for the given tag/commit hash.
@@ -108,20 +99,20 @@ const getCommitishDate = async (name, owner, target) => {
// Using Github GraphQL API get a list of PRs between the two "commitish" items.
// This resoves the "since" item's timestamp first and iterates over all PRs
// till "target" using naïve pagination.
const getHistory = async (name, owner, from, to) => {
LOG(`Fetching ${owner}/${name} PRs between ${from} and ${to}`);
const getHistory = async (name, owner, target, sinceDate) => {
LOG(`Fetching ${owner}/${name} PRs since ${sinceDate} till ${target}`);
const query = `
query findCommitsWithAssociatedPullRequests(
$name: String!
$owner: String!
$from: String!
$to: String!
$target: String!
$sinceDate: GitTimestamp
$cursor: String
) {
repository(name: $name, owner: $owner) {
ref(qualifiedName: $from) {
compare(headRef: $to) {
commits(first: 25, after: $cursor) {
object(expression: $target) {
... on Commit {
history(first: 50, since: $sinceDate, after: $cursor) {
totalCount
pageInfo {
hasNextPage
@@ -164,13 +155,13 @@ const getHistory = async (name, owner, from, to) => {
const result = await graphql(ghtoken, query, {
name,
owner,
from,
to,
target,
sinceDate,
cursor,
});
LOG(`GraphQL: ${JSON.stringify(result)}`);
nodes = [...nodes, ...result.repository.ref.compare.commits.nodes];
const { hasNextPage, endCursor } = result.repository.ref.compare.commits.pageInfo;
nodes = [...nodes, ...result.repository.object.history.nodes];
const { hasNextPage, endCursor } = result.repository.object.history.pageInfo;
if (!hasNextPage) {
break;
}
@@ -184,11 +175,11 @@ const getHistory = async (name, owner, from, to) => {
// feature, deprecation, breaking change and plugin fixes/enhancements).
//
// PR grouping relies on Github labels only, not on the PR contents.
const getChangeLogItems = async (name, owner, from, to) => {
const getChangeLogItems = async (name, owner, sinceDate, to) => {
// check if a node contains a certain label
const hasLabel = ({ labels }, label) => labels.nodes.some(({ name }) => name === label);
// get all the PRs between the two "commitish" items
const history = await getHistory(name, owner, from, to);
const history = await getHistory(name, owner, to, sinceDate);
const items = history.flatMap((node) => {
// discard PRs without a "changelog" label
@@ -240,10 +231,13 @@ const previous = process.argv[3] || process.env.INPUT_PREVIOUS || (await getPrev
LOG(`Previous tag/commit: ${previous}`);
const sinceDate = await getCommitishDate('grafana', 'grafana', previous);
LOG(`Previous tag/commit timestamp: ${sinceDate}`);
// Get all changelog items from Grafana OSS
const oss = await getChangeLogItems('grafana', 'grafana', previous, target);
const oss = await getChangeLogItems('grafana', 'grafana', sinceDate, target);
// Get all changelog items from Grafana Enterprise
const entr = await getChangeLogItems('grafana-enterprise', 'grafana', previous, target);
const entr = await getChangeLogItems('grafana-enterprise', 'grafana', sinceDate, target);
LOG(`Found OSS PRs: ${oss.length}`);
LOG(`Found Enterprise PRs: ${entr.length}`);
-16
View File
@@ -1,16 +0,0 @@
name: Add comment about adding a What's new note
on:
pull_request:
types: [labeled]
jobs:
add-comment:
if: ${{ ! github.event.pull_request.head.repo.fork && contains(github.event.pull_request.labels.*.name, 'add to what''s new') }}
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1
with:
message: |
Since you've added the `Add to what's new` label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.
+1
View File
@@ -12,6 +12,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
ref: main
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
@@ -11,7 +11,9 @@ on:
type: string
required: true
secrets:
token:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
outputs:
branch:
@@ -26,7 +28,9 @@ on:
type: string
required: true
secrets:
token:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
jobs:
main:
@@ -34,10 +38,16 @@ jobs:
outputs:
branch: ${{ steps.branch.outputs.branch }}
steps:
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: Create release branch
id: branch
uses: grafana/grafana-github-actions-go/bump-release@main
with:
ownerRepo: ${{ inputs.ownerRepo }}
source: ${{ inputs.source }}
token: ${{ secrets.token }}
token: ${{ steps.generate_token.outputs.token }}
-19
View File
@@ -1,19 +0,0 @@
name: Documentation CI
on:
pull_request:
branches: ["main"]
paths: ["docs/sources/**"]
workflow_dispatch:
jobs:
vale:
runs-on: ubuntu-latest
container:
image: grafana/vale:latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: grafana/writers-toolkit/vale-action@vale-action/v1
with:
filter: '.Name in ["Grafana.WordList", "Grafana.Spelling", "Grafana.ProductPossessives"]'
token: ${{ secrets.GITHUB_TOKEN }}
-30
View File
@@ -1,30 +0,0 @@
name: golangci-lint
on:
push:
paths:
- pkg/**
- .github/workflows/go-lint.yml
- go.*
branches:
- main
pull_request:
permissions:
contents: read
jobs:
lint-go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
- run: make gen-go
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.62.0
args: |
--verbose $(go list -m -f '{{.Dir}}' | xargs -I{} sh -c 'test ! -f {}/.nolint && echo {}/...')
install-mode: binary
+10 -47
View File
@@ -3,7 +3,7 @@ name: Crowdin Download Action
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
- cron: "0 * * * *"
jobs:
download-sources-from-crowdin:
@@ -12,7 +12,6 @@ jobs:
permissions:
contents: write # needed to commit changes into the PR
pull-requests: write # needed to update PR description, labels, etc
id-token: write # needed to get vault secrets
steps:
- name: Generate token
@@ -42,11 +41,17 @@ jobs:
pull_request_body: |
:robot: Automatic download of translations from Crowdin.
This runs once per day and will merge automatically if all the required checks pass.
Steps for merging:
1. A quick sanity check of the changes and approve. Things to look out for:
- No changes in the English file. The source of truth is in the main branch, NOT in Crowdin.
- Translations maybe be removed if the English phrase was removed, but there should not be many of these
- Anything else that looks 'funky'. Ask if you're not sure.
2. Approve & (Auto-)merge. :tada:
If there's a conflict, close the pull request and **delete the branch**.
You can then either wait for the schedule to trigger a new PR, or rerun the action manually.
If there's a conflict, close the pull request and **delete the branch**. A GH action will recreate the pull request.
Remember, the longer this pull request is open, the more likely it is that it'll get conflicts.
pull_request_labels: 'area/frontend, area/internationalization, no-changelog, no-backport'
pull_request_reviewers: 'grafana-frontend-platform'
pull_request_base_branch_name: 'main'
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
@@ -114,45 +119,3 @@ jobs:
with:
pr: ${{ steps.crowdin-download.outputs.pull_request_number }}
token: ${{ steps.generate_token.outputs.token }}
- name: Get vault secrets
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in ci/repo/grafana/grafana/grafana-pr-approver
repo_secrets: |
GRAFANA_PR_APPROVER_APP_ID=grafana-pr-approver:app-id
GRAFANA_PR_APPROVER_APP_PEM=grafana-pr-approver:private-key
- name: Generate approver token
if: steps.crowdin-download.outputs.pull_request_url
id: generate_approver_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ env.GRAFANA_PR_APPROVER_APP_ID }}
private_key: ${{ env.GRAFANA_PR_APPROVER_APP_PEM }}
- name: Approve and automerge PR
if: steps.crowdin-download.outputs.pull_request_url
shell: bash
# Only approve if:
# - the PR does not modify files other than json files under the public/locales/ directory
# - the PR does not modify the en-US locale
run: |
filesChanged=$(gh pr diff --name-only ${{ steps.crowdin-download.outputs.pull_request_url }})
if [[ $(echo $filesChanged | grep -v 'public/locales/[a-zA-Z\-]*/grafana.json' | wc -l) -ne 0 ]]; then
echo "Non-i18n changes detected, not approving"
exit 1
fi
if [[ $(echo $filesChanged | grep "public/locales/en-US" | wc -l) -ne 0 ]]; then
echo "public/locales/en-US changes detected, not approving"
exit 1
fi
echo "Approving and enabling automerge"
gh pr review ${{ steps.crowdin-download.outputs.pull_request_url }} --approve
gh pr merge --auto --squash ${{ steps.crowdin-download.outputs.pull_request_url }}
env:
GITHUB_TOKEN: ${{ steps.generate_approver_token.outputs.token }}
+13 -3
View File
@@ -16,7 +16,9 @@ on:
required: true
type: string
secrets:
token:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
workflow_dispatch:
inputs:
@@ -33,17 +35,25 @@ on:
required: true
type: string
secrets:
token:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: Migrate PRs
uses: grafana/grafana-github-actions-go/migrate-open-prs@main
with:
token: ${{ secrets.token }}
token: ${{ steps.generate_token.outputs.token }}
ownerRepo: ${{ inputs.ownerRepo }}
from: ${{ inputs.from }}
to: ${{ inputs.to }}
+15 -19
View File
@@ -19,7 +19,7 @@ on:
- closed
branches:
- 'main'
- 'v*.*.*'
- 'release-*.*.*'
jobs:
setup:
@@ -30,15 +30,8 @@ jobs:
release_branch: ${{ steps.output.outputs.release_branch }}
dry_run: ${{ steps.output.outputs.dry_run }}
latest: ${{ steps.output.outputs.latest }}
token: ${{ steps.output.outputs.token }}
runs-on: ubuntu-latest
steps:
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
# The github-release action expects a `LATEST` value of a string of either '1' or '0'
- if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
@@ -58,7 +51,6 @@ jobs:
echo "version: $VERSION"
echo "release_branch=$(echo $VERSION | sed -s 's/^v/release-/g')" >> "$GITHUB_OUTPUT"
echo "token=${{ steps.generate_token.outputs.token }}" >> "$GITHUB_OUTPUT"
echo "dry_run=$DRY_RUN" >> "$GITHUB_OUTPUT"
echo "latest=$LATEST" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
@@ -66,42 +58,46 @@ jobs:
name: Create next release branch (Grafana)
needs: setup
uses: ./.github/workflows/create-next-release-branch.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
with:
ownerRepo: 'grafana/grafana'
source: ${{ needs.setup.outputs.release_branch }}
secrets:
token: ${{ needs.setup.outputs.token }}
create_next_release_branch_enterprise:
name: Create next release branch (Grafana Enterprise)
needs: setup
uses: ./.github/workflows/create-next-release-branch.yml
with:
ownerRepo: 'grafana/grafana'
source: ${{ needs.setup.outputs.release_branch }}
secrets:
token: ${{ needs.setup.outputs.token }}
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
with:
ownerRepo: 'grafana/grafana-enterprise'
source: ${{ needs.setup.outputs.release_branch }}
migrate_prs_grafana:
needs:
- setup
- create_next_release_branch_grafana
uses: ./.github/workflows/migrate-prs.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
with:
ownerRepo: 'grafana/grafana'
from: ${{ needs.setup.outputs.release_branch }}
to: ${{ needs.create_next_release_branch_grafana.outputs.branch }}
secrets:
token: ${{ needs.setup.outputs.token }}
migrate_prs_enterprise:
needs:
- setup
- create_next_release_branch_enterprise
uses: ./.github/workflows/migrate-prs.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
with:
ownerRepo: 'grafana/grafana-enterprise'
from: ${{ needs.setup.outputs.release_branch }}
to: ${{ needs.create_next_release_branch_enterprise.outputs.branch }}
secrets:
token: ${{ needs.setup.outputs.token }}
post_changelog_on_forum:
needs: setup
uses: ./.github/workflows/community-release.yml
+1 -1
View File
@@ -143,7 +143,7 @@ jobs:
- name: Add package.json changes
run: |
git add package.json lerna.json yarn.lock packages public e2e/test-plugins
git add package.json lerna.json yarn.lock packages public
git commit -m "Update version to ${{ inputs.version }}"
- name: Git push
-44
View File
@@ -1,44 +0,0 @@
name: Run dashboard schema v2 e2e
on:
push:
branches:
- main
pull_request:
branches:
- '**'
env:
ARCH: linux-amd64
jobs:
dashboard-schema-v2-e2e:
runs-on: ubuntu-latest
continue-on-error: true
if: github.event.pull_request.draft == false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Pin Go version to mod file
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- run: go version
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Build grafana
run: make build
- name: Install Cypress dependencies
uses: cypress-io/github-action@v6
with:
runTests: false
- name: Run dashboard scenes e2e
run: yarn e2e:schema-v2 || echo "Test failed but marking as success since schema V2 is behind a feature flag and should not block PRs"
- name: Always succeed # This is a workaround to make the job pass even if the previous step fails
if: failure()
run: exit 0
+15
View File
@@ -0,0 +1,15 @@
name: syft-sbom-ci
on:
release:
types: [ published ]
workflow_dispatch:
jobs:
syft-sbom:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Anchore SBOM Action
uses: grafana/shared-workflows/actions@syft-sbom-v0.0.1
with:
artifact-name: ${{ github.event.repository.name }}-spdx.json
+5 -8
View File
@@ -27,14 +27,11 @@ jobs:
trivy fs --no-progress --download-db-only --db-repository public.ecr.aws/aquasecurity/trivy-db
- name: Run Trivy vulnerability scanner (table output)
# Use the trivy binary rather than the aquasecurity/trivy-action action
# to avoid a few bugs.
#
# We scan the file system rather than building the Docker image to only scan
# our direct dependencies. The Docker images are still scanned by
# Vulnerability Observability:
# - OSS: https://ops.grafana-ops.net/a/grafana-vulnerabilityobs-app/projects/sources/1
# - Enterprise: https://ops.grafana-ops.net/a/grafana-vulnerabilityobs-app/projects/sources/12
# (If these links are outdated, just go to the list and find the images manually.)
# to avoid a few bugs
# scan the filesystem, rather than building a Docker image prior - the
# downside is we won't catch dependencies that are only installed in the
# image, but the upside is we'll only catch vulnerabilities that are
# explicitly in the our dependencies
run: |
trivy fs \
--scanners vuln \
+6 -11
View File
@@ -40,7 +40,6 @@ __debug_bin*
# 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/signer
/devenv/docker/blocks/spanner_tests
/tmp
tools/phantomjs/phantomjs
@@ -104,18 +103,14 @@ profile.cov
/pkg/cmd/grafana-cli/grafana-cli
/pkg/cmd/grafana-server/grafana-server
/pkg/cmd/grafana-server/debug
# Extensions
/pkg/cmd/grafana-cli/runner/wireexts_enterprise.go
/pkg/server/wireexts_enterprise.go
/pkg/build/cmd/enterprise.go
/pkg/extensions/*
!/pkg/extensions/.keep
/pkg/build/cmd/artifactspage.go
/pkg/build/cmd/artifactspage.tmpl.html
/pkg/build/cmd/exportversion.go
/pkg/server/wireexts_enterprise.go
/pkg/cmd/grafana-cli/runner/wireexts_enterprise.go
!/pkg/extensions/main.go
/public/app/extensions
!/public/app/extensions/.keep
debug.test
/examples/*/dist
/packaging/**/*.rpm
@@ -175,13 +170,13 @@ compilation-stats.json
/e2e/benchmarks/**/results
/e2e/build_results.zip
/e2e/extensions
!/e2e/extensions/.keep
/e2e/extensions-suite
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
# grafana server
/scripts/grafana-server/server.log
+3 -3
View File
@@ -191,10 +191,10 @@ linters-settings:
allow: []
deny:
- pkg: github.com/grafana/grafana/pkg
desc: apps/investigations is not allowed to import grafana core
desc: apps/investigation is not allowed to import grafana core
files:
- ./apps/investigations/*
- ./apps/investigations/**/*
- ./apps/investigation/*
- ./apps/investigation/**/*
gocritic:
enabled-checks:
- ruleguard
-22
View File
@@ -1,22 +0,0 @@
# This is a trick to ignore files only by git but not by other tools
!/public/app/extensions
!/pkg/extensions/*
!/pkg/cmd/grafana-cli/runner/wireexts_enterprise.go
!/pkg/server/wireexts_enterprise.go
!/pkg/build/cmd/enterprise.go
!/pkg/extensions/*
# Enterprise emails
!/emails/templates/enterprise_*
!/public/emails/enterprise_*
# Enterprise reporting fonts
!/public/fonts/dejavu
# Enterprise devenv
!/devenv/docker/blocks/grafana-enterprise
!/devenv/docker/blocks/saml-enterprise
# 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/signer
!/devenv/docker/blocks/spanner_tests
-5
View File
@@ -1,5 +0,0 @@
MinAlertLevel = warning
[*]
BasedOnStyles = Grafana
TokenIgnores = (<http[^\n]+>+?), \*\*[^\n]+\*\*
+7 -21
View File
@@ -9,7 +9,12 @@
"program": "${workspaceFolder}/pkg/cmd/grafana/",
"env": {},
"cwd": "${workspaceFolder}",
"args": ["server", "--homepath", "${workspaceFolder}", "--packaging", "dev", "cfg:app_mode=development"]
"args": [
"server",
"--homepath", "${workspaceFolder}",
"--packaging", "dev",
"cfg:app_mode=development",
]
},
{
"name": "Attach to Test Process",
@@ -18,7 +23,7 @@
"mode": "remote",
"host": "127.0.0.1",
"port": 50480,
"apiVersion": 2
"apiVersion": 2,
},
{
"name": "Run API Server (testdata)",
@@ -67,16 +72,6 @@
"cwd": "${workspaceFolder}",
"args": ["server", "target", "--homepath", "${workspaceFolder}", "--packaging", "dev"]
},
{
"name": "Run Authz server",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/pkg/cmd/grafana/",
"env": { "GF_DEFAULT_TARGET": "zanzana-server", "GF_SERVER_HTTP_PORT": "3001" },
"cwd": "${workspaceFolder}",
"args": ["server", "target", "--homepath", "${workspaceFolder}", "--packaging", "dev"]
},
{
"name": "Attach to Chrome",
"port": 9222,
@@ -96,15 +91,6 @@
"NODE_ENV": "test"
}
},
{
"name": "Debug ESLint",
"type": "node",
"request": "launch",
"runtimeExecutable": "yarn",
"runtimeArgs": ["run", "eslint", "${file}"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "Debug Go test",
"type": "go",
+4
View File
@@ -13,6 +13,10 @@ packageExtensions:
doctrine@3.0.0:
dependencies:
assert: 2.0.0
rc-time-picker@3.7.3:
peerDependencies:
react: 17.0.1
react-dom: 17.0.1
rc-trigger@2.6.5:
peerDependencies:
react: 17.0.1
+25 -115
View File
@@ -1,3 +1,28 @@
<!-- 11.5.2 START -->
# 11.5.2 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99918](https://github.com/grafana/grafana/pull/99918), [@DanCech](https://github.com/DanCech)
- **TransformationFilter:** Include transformation outputs in transformation filtering options [#99878](https://github.com/grafana/grafana/pull/99878), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
- **grafana-ui:** Update InlineField error prop type to React.ReactNode [#100373](https://github.com/grafana/grafana/pull/100373), [@Clarity-89](https://github.com/Clarity-89)
### Bug fixes
- **Alerting:** Allow specifying uid for new rules added to groups [#100450](https://github.com/grafana/grafana/pull/100450), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Allow specifying uid for new rules added to groups [#100450](https://github.com/grafana/grafana/pull/100450), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Call RLock() before reading sendAlertsTo map [#99880](https://github.com/grafana/grafana/pull/99880), [@santihernandezc](https://github.com/santihernandezc)
- **Auth:** Fix redirect with JWT auth URL login [#100355](https://github.com/grafana/grafana/pull/100355), [@mgyongyosi](https://github.com/mgyongyosi)
- **AuthN:** Refetch user on "ErrUserAlreadyExists" [#100582](https://github.com/grafana/grafana/pull/100582), [@kalleep](https://github.com/kalleep)
- **Azure:** Correctly set application insights resource values [#99599](https://github.com/grafana/grafana/pull/99599), [@aangelisc](https://github.com/aangelisc)
- **CodeEditor:** Fix cursor alignment [#99863](https://github.com/grafana/grafana/pull/99863), [@ashharrison90](https://github.com/ashharrison90)
- **DashboardList:** Throttle the re-renders [#100046](https://github.com/grafana/grafana/pull/100046), [@bfmatei](https://github.com/bfmatei)
- **Dashboards:** Bring back scripted dashboards [#100633](https://github.com/grafana/grafana/pull/100633), [@dprokop](https://github.com/dprokop)
- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100078](https://github.com/grafana/grafana/pull/100078), [@clord](https://github.com/clord)
- **RBAC:** Don't check folder access if `annotationPermissionUpdate` FT is enabled [#100117](https://github.com/grafana/grafana/pull/100117), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
<!-- 11.5.2 END -->
<!-- 11.5.1 START -->
# 11.5.1 (2025-02-03)
@@ -176,121 +201,6 @@
- **Grafana UI:** Re-add react-router-dom as a dependency [#97540](https://github.com/grafana/grafana/pull/97540), [@leventebalogh](https://github.com/leventebalogh)
<!-- 11.5.0 END -->
<!-- 11.4.1 START -->
# 11.4.1 (2025-01-28)
### Features and enhancements
- **Security:** Update to Go 1.23.5 - Backport to v11.4.x [#99123](https://github.com/grafana/grafana/pull/99123), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.23.5 - Backport to v11.4.x (Enterprise)
### Bug fixes
- **Alerting:** AlertingQueryRunner should skip descendant nodes of invalid queries [#97830](https://github.com/grafana/grafana/pull/97830), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Fix alert rules unpausing after moving rule to different folder [#97583](https://github.com/grafana/grafana/pull/97583), [@santihernandezc](https://github.com/santihernandezc)
- **Alerting:** Fix label escaping in rule export [#98649](https://github.com/grafana/grafana/pull/98649), [@moustafab](https://github.com/moustafab)
- **Alerting:** Fix slack image uploading to use new api [#98066](https://github.com/grafana/grafana/pull/98066), [@moustafab](https://github.com/moustafab)
- **Azure/GCM:** Improve error display [#97594](https://github.com/grafana/grafana/pull/97594), [@aangelisc](https://github.com/aangelisc)
- **Dashboards:** Fix issue where filtered panels would not react to variable changes [#98734](https://github.com/grafana/grafana/pull/98734), [@oscarkilhed](https://github.com/oscarkilhed)
- **Dashboards:** Fixes issue with panel header showing even when hide time override was enabled [#98747](https://github.com/grafana/grafana/pull/98747), [@torkelo](https://github.com/torkelo)
- **Dashboards:** Fixes week relative time ranges when weekStart was changed [#98269](https://github.com/grafana/grafana/pull/98269), [@torkelo](https://github.com/torkelo)
- **Dashboards:** Panel react for `timeFrom` and `timeShift` changes using variables [#98659](https://github.com/grafana/grafana/pull/98659), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
- **DateTimePicker:** Fixes issue with date picker showing invalid date [#97971](https://github.com/grafana/grafana/pull/97971), [@torkelo](https://github.com/torkelo)
- **Fix:** Add support for datasource variable queries [#98119](https://github.com/grafana/grafana/pull/98119), [@sunker](https://github.com/sunker)
- **InfluxDB:** Adhoc filters can use template vars as values [#98786](https://github.com/grafana/grafana/pull/98786), [@bossinc](https://github.com/bossinc)
- **LibraryPanel:** Fallback to panel title if library panel title is not set [#99410](https://github.com/grafana/grafana/pull/99410), [@ivanortegaalba](https://github.com/ivanortegaalba)
### Plugin development fixes & changes
- **Grafana UI:** Re-add react-router-dom as a dependency [#98422](https://github.com/grafana/grafana/pull/98422), [@leventebalogh](https://github.com/leventebalogh)
<!-- 11.4.1 END -->
<!-- 11.3.3 START -->
# 11.3.3 (2025-01-28)
### Features and enhancements
- **Azure Monitor:** Add a feature flag to toggle user auth for Azure Monitor only [#97576](https://github.com/grafana/grafana/pull/97576), [@adamyeats](https://github.com/adamyeats)
- **Security:** Update to Go 1.23.5 - Backport to v11.3.x [#99124](https://github.com/grafana/grafana/pull/99124), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.23.5 - Backport to v11.3.x (Enterprise)
### Bug fixes
- **Alerting:** AlertingQueryRunner should skip descendant nodes of invalid queries [#97829](https://github.com/grafana/grafana/pull/97829), [@gillesdemey](https://github.com/gillesdemey)
- **Azure/GCM:** Improve error display [#97593](https://github.com/grafana/grafana/pull/97593), [@aangelisc](https://github.com/aangelisc)
- **Dashboard:** Fixes issue with compatability of old DashboardModel.annotations [#97467](https://github.com/grafana/grafana/pull/97467), [@torkelo](https://github.com/torkelo)
- **Dashboards:** Fix issue where filtered panels would not react to variable changes [#98733](https://github.com/grafana/grafana/pull/98733), [@oscarkilhed](https://github.com/oscarkilhed)
- **Dashboards:** Fixes issue with panel header showing even when hide time override was enabled [#97389](https://github.com/grafana/grafana/pull/97389), [@torkelo](https://github.com/torkelo)
- **Dashboards:** Fixes week relative time ranges when weekStart was changed [#98268](https://github.com/grafana/grafana/pull/98268), [@torkelo](https://github.com/torkelo)
- **DateTimePicker:** Fixes issue with date picker showing invalid date [#97970](https://github.com/grafana/grafana/pull/97970), [@torkelo](https://github.com/torkelo)
- **Fix:** Add support for datasource variable queries [#98118](https://github.com/grafana/grafana/pull/98118), [@sunker](https://github.com/sunker)
- **InfluxDB:** Adhoc filters can use template vars as values [#98785](https://github.com/grafana/grafana/pull/98785), [@bossinc](https://github.com/bossinc)
- **Unified Storage:** Use tls preferred when grafana db using ssl [#97379](https://github.com/grafana/grafana/pull/97379), [@owensmallwood](https://github.com/owensmallwood)
### Plugin development fixes & changes
- **Grafana UI:** Re-add react-router-dom as a dependency [#98421](https://github.com/grafana/grafana/pull/98421), [@leventebalogh](https://github.com/leventebalogh)
<!-- 11.3.3 END -->
<!-- 11.2.6 START -->
# 11.2.6 (2025-01-28)
### Features and enhancements
- **Azure Monitor:** Add a feature flag to toggle user auth for Azure Monitor only [#97565](https://github.com/grafana/grafana/pull/97565), [@adamyeats](https://github.com/adamyeats)
- **Security:** Update to Go 1.22.11 - Backport to v11.2.x [#99125](https://github.com/grafana/grafana/pull/99125), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.22.11 - Backport to v11.2.x (Enterprise)
### Bug fixes
- **Azure/GCM:** Improve error display [#97591](https://github.com/grafana/grafana/pull/97591), [@aangelisc](https://github.com/aangelisc)
<!-- 11.2.6 END -->
<!-- 11.1.11 START -->
# 11.1.11 (2025-01-28)
### Features and enhancements
- **Security:** Update to Go 1.22.11 - Backport to v11.1.x [#99126](https://github.com/grafana/grafana/pull/99126), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.22.11 - Backport to v11.1.x (Enterprise)
### Bug fixes
- **Azure/GCM:** Improve error display [#97595](https://github.com/grafana/grafana/pull/97595), [@aangelisc](https://github.com/aangelisc)
<!-- 11.1.11 END -->
<!-- 11.0.10 START -->
# 11.0.10 (2025-01-28)
### Features and enhancements
- **Security:** Update to Go 1.22.11 - Backport to v11.0.x [#99127](https://github.com/grafana/grafana/pull/99127), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.22.11 - Backport to v11.0.x (Enterprise)
### Bug fixes
- **Azure/GCM:** Improve error display [#97592](https://github.com/grafana/grafana/pull/97592), [@aangelisc](https://github.com/aangelisc)
<!-- 11.0.10 END -->
<!-- 10.4.15 START -->
# 10.4.15 (2025-01-28)
### Features and enhancements
- **Security:** Update to Go 1.22.11 - Backport to v10.4.x [#99128](https://github.com/grafana/grafana/pull/99128), [@Proximyst](https://github.com/Proximyst)
- **Security:** Update to Go 1.22.11 - Backport to v10.4.x (Enterprise)
### Bug fixes
- **Azure/GCM:** Improve error display [#97590](https://github.com/grafana/grafana/pull/97590), [@aangelisc](https://github.com/aangelisc)
<!-- 10.4.15 END -->
<!-- 11.4.0 START -->
# 11.4.0 (2024-12-05)
+18 -18
View File
@@ -3,10 +3,10 @@
# to maintain formatting of multiline commands in vscode, add the following to settings.json:
# "docker.languageserver.formatter.ignoreMultilineInstructions": true
ARG BASE_IMAGE=alpine:3.20
ARG BASE_IMAGE=alpine:3.21
ARG JS_IMAGE=node:22-alpine
ARG JS_PLATFORM=linux/amd64
ARG GO_IMAGE=golang:1.23.5-alpine
ARG GO_IMAGE=golang:1.23.7-alpine
# Default to building locally
ARG GO_SRC=go-builder
@@ -22,6 +22,7 @@ WORKDIR /tmp/grafana
COPY package.json project.json nx.json yarn.lock .yarnrc.yml ./
COPY .yarn .yarn
COPY packages packages
COPY plugins-bundled plugins-bundled
COPY public public
COPY LICENSE ./
COPY conf/defaults.ini ./conf/defaults.ini
@@ -62,24 +63,23 @@ COPY go.* ./
COPY .bingo .bingo
# Include vendored dependencies
COPY pkg/util/xorm pkg/util/xorm
COPY pkg/apiserver pkg/apiserver
COPY pkg/apimachinery pkg/apimachinery
COPY pkg/build pkg/build
COPY pkg/build/wire pkg/build/wire
COPY pkg/promlib pkg/promlib
COPY pkg/storage/unified/resource pkg/storage/unified/resource
COPY pkg/storage/unified/apistore pkg/storage/unified/apistore
COPY pkg/semconv pkg/semconv
COPY pkg/aggregator pkg/aggregator
COPY apps/playlist apps/playlist
COPY apps/investigations apps/investigations
COPY apps/advisor apps/advisor
COPY pkg/util/xorm/go.* pkg/util/xorm/
COPY pkg/apiserver/go.* pkg/apiserver/
COPY pkg/apimachinery/go.* pkg/apimachinery/
COPY pkg/build/go.* pkg/build/
COPY pkg/build/wire/go.* pkg/build/wire/
COPY pkg/promlib/go.* pkg/promlib/
COPY pkg/storage/unified/resource/go.* pkg/storage/unified/resource/
COPY pkg/storage/unified/apistore/go.* pkg/storage/unified/apistore/
COPY pkg/semconv/go.* pkg/semconv/
COPY pkg/aggregator/go.* pkg/aggregator/
COPY apps/playlist/go.* apps/playlist/
COPY apps/investigation/go.* apps/investigation/
COPY apps apps
COPY kindsv2 kindsv2
COPY apps/alerting/notifications apps/alerting/notifications
COPY pkg/codegen pkg/codegen
COPY pkg/plugins/codegen pkg/plugins/codegen
COPY apps/alerting/notifications/go.* apps/alerting/notifications/
COPY pkg/codegen/go.* pkg/codegen/
COPY pkg/plugins/codegen/go.* pkg/plugins/codegen/
RUN go mod download
RUN if [[ "$BINGO" = "true" ]]; then \
+1 -1
View File
@@ -8,4 +8,4 @@
- @davkal
- Docs:
- @chri2547
- @JohnnyK-Grafana
- @brendamuir
+3 -11
View File
@@ -8,7 +8,7 @@ WIRE_TAGS = "oss"
include .bingo/Variables.mk
GO = go
GO_VERSION = 1.23.5
GO_VERSION = 1.23.7
GO_LINT_FILES ?= $(shell ./scripts/go-workspace/golangci-lint-includes.sh)
GO_TEST_FILES ?= $(shell ./scripts/go-workspace/test-includes.sh)
SH_FILES ?= $(shell find ./scripts -name *.sh)
@@ -149,7 +149,7 @@ gen-cue: ## Do all CUE/Thema code generation
.PHONY: gen-cuev2
gen-cuev2: ## Do all CUE code generation
@echo "generate code from .cue files (v2)"
@$(MAKE) -C ./kindsv2 all
go generate ./kindsv2/gen.go
.PHONY: gen-feature-toggles
gen-feature-toggles:
@@ -211,6 +211,7 @@ build-cli: ## Build Grafana CLI application.
build-js: ## Build frontend assets.
@echo "build frontend"
yarn run build
yarn run plugins:build-bundled
PLUGIN_ID ?=
@@ -271,14 +272,6 @@ test-go-integration-alertmanager: ## Run integration tests for the remote alertm
AM_URL=http://localhost:8080 AM_TENANT_ID=test \
$(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegrationRemoteAlertmanager" -covermode=atomic -timeout=5m ./pkg/services/ngalert/...
.PHONY: test-go-integration-grafana-alertmanager
test-go-integration-grafana-alertmanager: ## Run integration tests for the grafana alertmanager
@echo "test grafana alertmanager integration tests"
@export GRAFANA_VERSION=11.5.0-81938; \
$(GO) run tools/setup_grafana_alertmanager_integration_test_images.go; \
$(GO) clean -testcache; \
$(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestAlertmanagerIntegration" -covermode=atomic -timeout=10m ./pkg/tests/alertmanager/...
.PHONY: test-go-integration-postgres
test-go-integration-postgres: devenv-postgres ## Run integration tests for postgres backend with flags.
@echo "test backend integration postgres tests"
@@ -429,7 +422,6 @@ protobuf: ## Compile protobuf definitions
buf generate pkg/plugins/backendplugin/secretsmanagerplugin --template pkg/plugins/backendplugin/secretsmanagerplugin/buf.gen.yaml
buf generate pkg/storage/unified/resource --template pkg/storage/unified/resource/buf.gen.yaml
buf generate pkg/services/authz/proto/v1 --template pkg/services/authz/proto/v1/buf.gen.yaml
buf generate pkg/services/ngalert/store/proto/v1 --template pkg/services/ngalert/store/proto/v1/buf.gen.yaml
.PHONY: clean
clean: ## Clean up intermediate build artifacts.
+1 -1
View File
@@ -43,7 +43,7 @@ If you're interested in contributing to the Grafana project:
- If you have a specific question, check out our [discussion forums](https://community.grafana.com/).
- For general discussions, join us on the [official Slack](https://slack.grafana.com) team.
This project is tested with [BrowserStack](https://www.browserstack.com/).
This project is tested with [BrowserStack](https://www.browserstack.com/)
## License
-1
View File
@@ -1 +0,0 @@
plugin/src
-3
View File
@@ -1,3 +0,0 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
-85
View File
@@ -1,85 +0,0 @@
module github.com/grafana/grafana/apps/advisor
go 1.23.4
require (
github.com/grafana/grafana-app-sdk v0.31.0
k8s.io/apimachinery v0.32.0
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/cenkalti/backoff/v4 v4.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/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.128.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.29.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.61.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.33.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
go.opentelemetry.io/otel/metric v1.33.0 // indirect
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
go.opentelemetry.io/otel/trace v1.33.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
google.golang.org/grpc v1.69.4 // indirect
google.golang.org/protobuf v1.36.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.0 // indirect
k8s.io/apiextensions-apiserver v0.32.0 // indirect
k8s.io/client-go v0.32.0 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
-226
View File
@@ -1,226 +0,0 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4=
github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-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-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.30.0 h1:Hqn2pETu2mQ4RpWkZYEQfu01P7xd1Z1Gj+HX/8aB0tw=
github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1GTNtyNuExONtiNuk=
github.com/grafana/grafana-app-sdk/logging v0.29.0 h1:mgbXaAf33aFwqwGVeaX30l8rkeAJH0iACgX5Rn6YkN4=
github.com/grafana/grafana-app-sdk/logging v0.29.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/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/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/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
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/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
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/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/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
-49
View File
@@ -1,49 +0,0 @@
package advisor
check: {
kind: "Check"
pluralName: "Checks"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
frontend: true
backend: true
}
validation: {
operations: [
"CREATE",
"UPDATE",
]
}
schema: {
#Data: {
// Generic data input that a check can receive
data?: [string]: string
}
#ReportFailure: {
// Severity of the failure
severity: "high" | "low"
// Human readable reason for the failure
reason: string
// Action to take to resolve the failure
action: string
// Step ID that the failure is associated with
stepID: string
// Item ID that the failure is associated with
itemID: string
}
#Report: {
// Number of elements analyzed
count: int
// List of failures
failures: [...#ReportFailure]
}
spec: #Data
status: {
report: #Report
}
}
}
}
}
-26
View File
@@ -1,26 +0,0 @@
package advisor
checktype: {
kind: "CheckType"
pluralName: "CheckTypes"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
frontend: true
backend: true
}
schema: {
#Step: {
title: string
description: string
stepID: string
}
spec: {
name: string
steps: [...#Step]
}
}
}
}
}
-4
View File
@@ -1,4 +0,0 @@
module: "github.com/grafana/grafana/apps/advisor/kinds"
language: {
version: "v0.9.0"
}
-10
View File
@@ -1,10 +0,0 @@
package advisor
manifest: {
appName: "advisor"
groupOverride: "advisor.grafana.app"
kinds: [
check,
checktype,
]
}
@@ -1,28 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"encoding/json"
"io"
"github.com/grafana/grafana-app-sdk/resource"
)
// CheckJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
type CheckJSONCodec struct{}
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
func (*CheckJSONCodec) Read(reader io.Reader, into resource.Object) error {
return json.NewDecoder(reader).Decode(into)
}
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
func (*CheckJSONCodec) Write(writer io.Writer, from resource.Object) error {
return json.NewEncoder(writer).Encode(from)
}
// Interface compliance checks
var _ resource.Codec = &CheckJSONCodec{}
@@ -1,28 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
time "time"
)
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
type CheckMetadata struct {
UpdateTimestamp time.Time `json:"updateTimestamp"`
CreatedBy string `json:"createdBy"`
Uid string `json:"uid"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
ResourceVersion string `json:"resourceVersion"`
Generation int64 `json:"generation"`
UpdatedBy string `json:"updatedBy"`
Labels map[string]string `json:"labels"`
}
// NewCheckMetadata creates a new CheckMetadata object.
func NewCheckMetadata() *CheckMetadata {
return &CheckMetadata{}
}
@@ -1,266 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"time"
)
// +k8s:openapi-gen=true
type Check struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
Spec CheckSpec `json:"spec" yaml:"spec"`
CheckStatus CheckStatus `json:"status" yaml:"status"`
}
func (o *Check) GetSpec() any {
return o.Spec
}
func (o *Check) SetSpec(spec any) error {
cast, ok := spec.(CheckSpec)
if !ok {
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
}
o.Spec = cast
return nil
}
func (o *Check) GetSubresources() map[string]any {
return map[string]any{
"status": o.CheckStatus,
}
}
func (o *Check) GetSubresource(name string) (any, bool) {
switch name {
case "status":
return o.CheckStatus, true
default:
return nil, false
}
}
func (o *Check) SetSubresource(name string, value any) error {
switch name {
case "status":
cast, ok := value.(CheckStatus)
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type CheckStatus", value)
}
o.CheckStatus = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
}
}
func (o *Check) GetStaticMetadata() resource.StaticMetadata {
gvk := o.GroupVersionKind()
return resource.StaticMetadata{
Name: o.ObjectMeta.Name,
Namespace: o.ObjectMeta.Namespace,
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
}
}
func (o *Check) SetStaticMetadata(metadata resource.StaticMetadata) {
o.Name = metadata.Name
o.Namespace = metadata.Namespace
o.SetGroupVersionKind(schema.GroupVersionKind{
Group: metadata.Group,
Version: metadata.Version,
Kind: metadata.Kind,
})
}
func (o *Check) GetCommonMetadata() resource.CommonMetadata {
dt := o.DeletionTimestamp
var deletionTimestamp *time.Time
if dt != nil {
deletionTimestamp = &dt.Time
}
// Legacy ExtraFields support
extraFields := make(map[string]any)
if o.Annotations != nil {
extraFields["annotations"] = o.Annotations
}
if o.ManagedFields != nil {
extraFields["managedFields"] = o.ManagedFields
}
if o.OwnerReferences != nil {
extraFields["ownerReferences"] = o.OwnerReferences
}
return resource.CommonMetadata{
UID: string(o.UID),
ResourceVersion: o.ResourceVersion,
Generation: o.Generation,
Labels: o.Labels,
CreationTimestamp: o.CreationTimestamp.Time,
DeletionTimestamp: deletionTimestamp,
Finalizers: o.Finalizers,
UpdateTimestamp: o.GetUpdateTimestamp(),
CreatedBy: o.GetCreatedBy(),
UpdatedBy: o.GetUpdatedBy(),
ExtraFields: extraFields,
}
}
func (o *Check) SetCommonMetadata(metadata resource.CommonMetadata) {
o.UID = types.UID(metadata.UID)
o.ResourceVersion = metadata.ResourceVersion
o.Generation = metadata.Generation
o.Labels = metadata.Labels
o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
if metadata.DeletionTimestamp != nil {
dt := metav1.NewTime(*metadata.DeletionTimestamp)
o.DeletionTimestamp = &dt
} else {
o.DeletionTimestamp = nil
}
o.Finalizers = metadata.Finalizers
if o.Annotations == nil {
o.Annotations = make(map[string]string)
}
if !metadata.UpdateTimestamp.IsZero() {
o.SetUpdateTimestamp(metadata.UpdateTimestamp)
}
if metadata.CreatedBy != "" {
o.SetCreatedBy(metadata.CreatedBy)
}
if metadata.UpdatedBy != "" {
o.SetUpdatedBy(metadata.UpdatedBy)
}
// Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
if metadata.ExtraFields != nil {
if annotations, ok := metadata.ExtraFields["annotations"]; ok {
if cast, ok := annotations.(map[string]string); ok {
o.Annotations = cast
}
}
if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
o.ManagedFields = cast
}
}
if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
o.OwnerReferences = cast
}
}
}
}
func (o *Check) GetCreatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
}
func (o *Check) SetCreatedBy(createdBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
}
func (o *Check) GetUpdateTimestamp() time.Time {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
return parsed
}
func (o *Check) SetUpdateTimestamp(updateTimestamp time.Time) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
}
func (o *Check) GetUpdatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
}
func (o *Check) SetUpdatedBy(updatedBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
}
func (o *Check) Copy() resource.Object {
return resource.CopyObject(o)
}
func (o *Check) DeepCopyObject() runtime.Object {
return o.Copy()
}
// Interface compliance compile-time check
var _ resource.Object = &Check{}
// +k8s:openapi-gen=true
type CheckList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []Check `json:"items" yaml:"items"`
}
func (o *CheckList) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *CheckList) Copy() resource.ListObject {
cpy := &CheckList{
TypeMeta: o.TypeMeta,
Items: make([]Check, len(o.Items)),
}
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
for i := 0; i < len(o.Items); i++ {
if item, ok := o.Items[i].Copy().(*Check); ok {
cpy.Items[i] = *item
}
}
return cpy
}
func (o *CheckList) GetItems() []resource.Object {
items := make([]resource.Object, len(o.Items))
for i := 0; i < len(o.Items); i++ {
items[i] = &o.Items[i]
}
return items
}
func (o *CheckList) SetItems(items []resource.Object) {
o.Items = make([]Check, len(items))
for i := 0; i < len(items); i++ {
o.Items[i] = *items[i].(*Check)
}
}
// Interface compliance compile-time check
var _ resource.ListObject = &CheckList{}
@@ -1,34 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaCheck = resource.NewSimpleSchema("advisor.grafana.app", "v0alpha1", &Check{}, &CheckList{}, resource.WithKind("Check"),
resource.WithPlural("checks"), resource.WithScope(resource.NamespacedScope))
kindCheck = resource.Kind{
Schema: schemaCheck,
Codecs: map[resource.KindEncoding]resource.Codec{
resource.KindEncodingJSON: &CheckJSONCodec{},
},
}
)
// Kind returns a resource.Kind for this Schema with a JSON codec
func CheckKind() resource.Kind {
return kindCheck
}
// Schema returns a resource.SimpleSchema representation of Check
func CheckSchema() *resource.SimpleSchema {
return schemaCheck
}
// Interface compliance checks
var _ resource.Schema = kindCheck
@@ -1,14 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type CheckSpec struct {
// Generic data input that a check can receive
Data map[string]string `json:"data,omitempty"`
}
// NewCheckSpec creates a new CheckSpec object.
func NewCheckSpec() *CheckSpec {
return &CheckSpec{}
}
@@ -1,87 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type CheckReportFailure struct {
// Severity of the failure
Severity CheckReportFailureSeverity `json:"severity"`
// Human readable reason for the failure
Reason string `json:"reason"`
// Action to take to resolve the failure
Action string `json:"action"`
// Step ID that the failure is associated with
StepID string `json:"stepID"`
// Item ID that the failure is associated with
ItemID string `json:"itemID"`
}
// NewCheckReportFailure creates a new CheckReportFailure object.
func NewCheckReportFailure() *CheckReportFailure {
return &CheckReportFailure{}
}
// +k8s:openapi-gen=true
type CheckstatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State CheckStatusOperatorStateState `json:"state"`
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
}
// NewCheckstatusOperatorState creates a new CheckstatusOperatorState object.
func NewCheckstatusOperatorState() *CheckstatusOperatorState {
return &CheckstatusOperatorState{}
}
// +k8s:openapi-gen=true
type CheckStatus struct {
Report CheckV0alpha1StatusReport `json:"report"`
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]CheckstatusOperatorState `json:"operatorStates,omitempty"`
// additionalFields is reserved for future use
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
}
// NewCheckStatus creates a new CheckStatus object.
func NewCheckStatus() *CheckStatus {
return &CheckStatus{
Report: *NewCheckV0alpha1StatusReport(),
}
}
// +k8s:openapi-gen=true
type CheckReportFailureSeverity string
const (
CheckReportFailureSeverityHigh CheckReportFailureSeverity = "high"
CheckReportFailureSeverityLow CheckReportFailureSeverity = "low"
)
// +k8s:openapi-gen=true
type CheckStatusOperatorStateState string
const (
CheckStatusOperatorStateStateSuccess CheckStatusOperatorStateState = "success"
CheckStatusOperatorStateStateInProgress CheckStatusOperatorStateState = "in_progress"
CheckStatusOperatorStateStateFailed CheckStatusOperatorStateState = "failed"
)
// +k8s:openapi-gen=true
type CheckV0alpha1StatusReport struct {
// Number of elements analyzed
Count int64 `json:"count"`
// List of failures
Failures []CheckReportFailure `json:"failures"`
}
// NewCheckV0alpha1StatusReport creates a new CheckV0alpha1StatusReport object.
func NewCheckV0alpha1StatusReport() *CheckV0alpha1StatusReport {
return &CheckV0alpha1StatusReport{}
}
@@ -1,28 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"encoding/json"
"io"
"github.com/grafana/grafana-app-sdk/resource"
)
// CheckTypeJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
type CheckTypeJSONCodec struct{}
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
func (*CheckTypeJSONCodec) Read(reader io.Reader, into resource.Object) error {
return json.NewDecoder(reader).Decode(into)
}
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
func (*CheckTypeJSONCodec) Write(writer io.Writer, from resource.Object) error {
return json.NewEncoder(writer).Encode(from)
}
// Interface compliance checks
var _ resource.Codec = &CheckTypeJSONCodec{}
@@ -1,28 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
time "time"
)
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
type CheckTypeMetadata struct {
UpdateTimestamp time.Time `json:"updateTimestamp"`
CreatedBy string `json:"createdBy"`
Uid string `json:"uid"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
ResourceVersion string `json:"resourceVersion"`
Generation int64 `json:"generation"`
UpdatedBy string `json:"updatedBy"`
Labels map[string]string `json:"labels"`
}
// NewCheckTypeMetadata creates a new CheckTypeMetadata object.
func NewCheckTypeMetadata() *CheckTypeMetadata {
return &CheckTypeMetadata{}
}
@@ -1,266 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"fmt"
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"time"
)
// +k8s:openapi-gen=true
type CheckType struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
Spec CheckTypeSpec `json:"spec" yaml:"spec"`
CheckTypeStatus CheckTypeStatus `json:"status" yaml:"status"`
}
func (o *CheckType) GetSpec() any {
return o.Spec
}
func (o *CheckType) SetSpec(spec any) error {
cast, ok := spec.(CheckTypeSpec)
if !ok {
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
}
o.Spec = cast
return nil
}
func (o *CheckType) GetSubresources() map[string]any {
return map[string]any{
"status": o.CheckTypeStatus,
}
}
func (o *CheckType) GetSubresource(name string) (any, bool) {
switch name {
case "status":
return o.CheckTypeStatus, true
default:
return nil, false
}
}
func (o *CheckType) SetSubresource(name string, value any) error {
switch name {
case "status":
cast, ok := value.(CheckTypeStatus)
if !ok {
return fmt.Errorf("cannot set status type %#v, not of type CheckTypeStatus", value)
}
o.CheckTypeStatus = cast
return nil
default:
return fmt.Errorf("subresource '%s' does not exist", name)
}
}
func (o *CheckType) GetStaticMetadata() resource.StaticMetadata {
gvk := o.GroupVersionKind()
return resource.StaticMetadata{
Name: o.ObjectMeta.Name,
Namespace: o.ObjectMeta.Namespace,
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
}
}
func (o *CheckType) SetStaticMetadata(metadata resource.StaticMetadata) {
o.Name = metadata.Name
o.Namespace = metadata.Namespace
o.SetGroupVersionKind(schema.GroupVersionKind{
Group: metadata.Group,
Version: metadata.Version,
Kind: metadata.Kind,
})
}
func (o *CheckType) GetCommonMetadata() resource.CommonMetadata {
dt := o.DeletionTimestamp
var deletionTimestamp *time.Time
if dt != nil {
deletionTimestamp = &dt.Time
}
// Legacy ExtraFields support
extraFields := make(map[string]any)
if o.Annotations != nil {
extraFields["annotations"] = o.Annotations
}
if o.ManagedFields != nil {
extraFields["managedFields"] = o.ManagedFields
}
if o.OwnerReferences != nil {
extraFields["ownerReferences"] = o.OwnerReferences
}
return resource.CommonMetadata{
UID: string(o.UID),
ResourceVersion: o.ResourceVersion,
Generation: o.Generation,
Labels: o.Labels,
CreationTimestamp: o.CreationTimestamp.Time,
DeletionTimestamp: deletionTimestamp,
Finalizers: o.Finalizers,
UpdateTimestamp: o.GetUpdateTimestamp(),
CreatedBy: o.GetCreatedBy(),
UpdatedBy: o.GetUpdatedBy(),
ExtraFields: extraFields,
}
}
func (o *CheckType) SetCommonMetadata(metadata resource.CommonMetadata) {
o.UID = types.UID(metadata.UID)
o.ResourceVersion = metadata.ResourceVersion
o.Generation = metadata.Generation
o.Labels = metadata.Labels
o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
if metadata.DeletionTimestamp != nil {
dt := metav1.NewTime(*metadata.DeletionTimestamp)
o.DeletionTimestamp = &dt
} else {
o.DeletionTimestamp = nil
}
o.Finalizers = metadata.Finalizers
if o.Annotations == nil {
o.Annotations = make(map[string]string)
}
if !metadata.UpdateTimestamp.IsZero() {
o.SetUpdateTimestamp(metadata.UpdateTimestamp)
}
if metadata.CreatedBy != "" {
o.SetCreatedBy(metadata.CreatedBy)
}
if metadata.UpdatedBy != "" {
o.SetUpdatedBy(metadata.UpdatedBy)
}
// Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
if metadata.ExtraFields != nil {
if annotations, ok := metadata.ExtraFields["annotations"]; ok {
if cast, ok := annotations.(map[string]string); ok {
o.Annotations = cast
}
}
if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
o.ManagedFields = cast
}
}
if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
o.OwnerReferences = cast
}
}
}
}
func (o *CheckType) GetCreatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
}
func (o *CheckType) SetCreatedBy(createdBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
}
func (o *CheckType) GetUpdateTimestamp() time.Time {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
return parsed
}
func (o *CheckType) SetUpdateTimestamp(updateTimestamp time.Time) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
}
func (o *CheckType) GetUpdatedBy() string {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
}
func (o *CheckType) SetUpdatedBy(updatedBy string) {
if o.ObjectMeta.Annotations == nil {
o.ObjectMeta.Annotations = make(map[string]string)
}
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
}
func (o *CheckType) Copy() resource.Object {
return resource.CopyObject(o)
}
func (o *CheckType) DeepCopyObject() runtime.Object {
return o.Copy()
}
// Interface compliance compile-time check
var _ resource.Object = &CheckType{}
// +k8s:openapi-gen=true
type CheckTypeList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []CheckType `json:"items" yaml:"items"`
}
func (o *CheckTypeList) DeepCopyObject() runtime.Object {
return o.Copy()
}
func (o *CheckTypeList) Copy() resource.ListObject {
cpy := &CheckTypeList{
TypeMeta: o.TypeMeta,
Items: make([]CheckType, len(o.Items)),
}
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
for i := 0; i < len(o.Items); i++ {
if item, ok := o.Items[i].Copy().(*CheckType); ok {
cpy.Items[i] = *item
}
}
return cpy
}
func (o *CheckTypeList) GetItems() []resource.Object {
items := make([]resource.Object, len(o.Items))
for i := 0; i < len(o.Items); i++ {
items[i] = &o.Items[i]
}
return items
}
func (o *CheckTypeList) SetItems(items []resource.Object) {
o.Items = make([]CheckType, len(items))
for i := 0; i < len(items); i++ {
o.Items[i] = *items[i].(*CheckType)
}
}
// Interface compliance compile-time check
var _ resource.ListObject = &CheckTypeList{}
@@ -1,34 +0,0 @@
//
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
)
// schema is unexported to prevent accidental overwrites
var (
schemaCheckType = resource.NewSimpleSchema("advisor.grafana.app", "v0alpha1", &CheckType{}, &CheckTypeList{}, resource.WithKind("CheckType"),
resource.WithPlural("checktypes"), resource.WithScope(resource.NamespacedScope))
kindCheckType = resource.Kind{
Schema: schemaCheckType,
Codecs: map[resource.KindEncoding]resource.Codec{
resource.KindEncodingJSON: &CheckTypeJSONCodec{},
},
}
)
// Kind returns a resource.Kind for this Schema with a JSON codec
func CheckTypeKind() resource.Kind {
return kindCheckType
}
// Schema returns a resource.SimpleSchema representation of CheckType
func CheckTypeSchema() *resource.SimpleSchema {
return schemaCheckType
}
// Interface compliance checks
var _ resource.Schema = kindCheckType
@@ -1,26 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type CheckTypeStep struct {
Title string `json:"title"`
Description string `json:"description"`
StepID string `json:"stepID"`
}
// NewCheckTypeStep creates a new CheckTypeStep object.
func NewCheckTypeStep() *CheckTypeStep {
return &CheckTypeStep{}
}
// +k8s:openapi-gen=true
type CheckTypeSpec struct {
Name string `json:"name"`
Steps []CheckTypeStep `json:"steps"`
}
// NewCheckTypeSpec creates a new CheckTypeSpec object.
func NewCheckTypeSpec() *CheckTypeSpec {
return &CheckTypeSpec{}
}
@@ -1,44 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type CheckTypestatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State CheckTypeStatusOperatorStateState `json:"state"`
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
}
// NewCheckTypestatusOperatorState creates a new CheckTypestatusOperatorState object.
func NewCheckTypestatusOperatorState() *CheckTypestatusOperatorState {
return &CheckTypestatusOperatorState{}
}
// +k8s:openapi-gen=true
type CheckTypeStatus struct {
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]CheckTypestatusOperatorState `json:"operatorStates,omitempty"`
// additionalFields is reserved for future use
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
}
// NewCheckTypeStatus creates a new CheckTypeStatus object.
func NewCheckTypeStatus() *CheckTypeStatus {
return &CheckTypeStatus{}
}
// +k8s:openapi-gen=true
type CheckTypeStatusOperatorStateState string
const (
CheckTypeStatusOperatorStateStateSuccess CheckTypeStatusOperatorStateState = "success"
CheckTypeStatusOperatorStateStateInProgress CheckTypeStatusOperatorStateState = "in_progress"
CheckTypeStatusOperatorStateStateFailed CheckTypeStatusOperatorStateState = "failed"
)
@@ -1,18 +0,0 @@
package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema"
const (
// Group is the API group used by all kinds in this package
Group = "advisor.grafana.app"
// Version is the API version used by all kinds in this package
Version = "v0alpha1"
)
var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{
Group: Group,
Version: Version,
}
)
-73
View File
@@ -1,73 +0,0 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package apis
import (
"encoding/json"
"github.com/grafana/grafana-app-sdk/app"
)
var (
rawSchemaCheckv0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"type":"string"},"description":"Generic data input that a check can receive","type":"object"}},"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"report":{"properties":{"count":{"description":"Number of elements analyzed","type":"integer"},"failures":{"description":"List of failures","items":{"properties":{"action":{"description":"Action to take to resolve the failure","type":"string"},"itemID":{"description":"Item ID that the failure is associated with","type":"string"},"reason":{"description":"Human readable reason for the failure","type":"string"},"severity":{"description":"Severity of the failure","enum":["high","low"],"type":"string"},"stepID":{"description":"Step ID that the failure is associated with","type":"string"}},"required":["severity","reason","action","stepID","itemID"],"type":"object"},"type":"array"}},"required":["count","failures"],"type":"object"}},"required":["report"],"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
versionSchemaCheckv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaCheckv0alpha1, &versionSchemaCheckv0alpha1)
rawSchemaCheckTypev0alpha1 = []byte(`{"spec":{"properties":{"name":{"type":"string"},"steps":{"items":{"properties":{"description":{"type":"string"},"stepID":{"type":"string"},"title":{"type":"string"}},"required":["title","description","stepID"],"type":"object"},"type":"array"}},"required":["name","steps"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
versionSchemaCheckTypev0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaCheckTypev0alpha1, &versionSchemaCheckTypev0alpha1)
)
var appManifestData = app.ManifestData{
AppName: "advisor",
Group: "advisor.grafana.app",
Kinds: []app.ManifestKind{
{
Kind: "Check",
Scope: "Namespaced",
Conversion: false,
Versions: []app.ManifestKindVersion{
{
Name: "v0alpha1",
Admission: &app.AdmissionCapabilities{
Validation: &app.ValidationCapability{
Operations: []app.AdmissionOperation{
app.AdmissionOperationCreate,
app.AdmissionOperationUpdate,
},
},
},
Schema: &versionSchemaCheckv0alpha1,
},
},
},
{
Kind: "CheckType",
Scope: "Namespaced",
Conversion: false,
Versions: []app.ManifestKindVersion{
{
Name: "v0alpha1",
Schema: &versionSchemaCheckTypev0alpha1,
},
},
},
},
}
func jsonToMap(j string) map[string]any {
m := make(map[string]any)
json.Unmarshal([]byte(j), &j)
return m
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("advisor")
}
-116
View File
@@ -1,116 +0,0 @@
package app
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/k8s"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana-app-sdk/simple"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/apps/advisor/pkg/app/checkscheduler"
"github.com/grafana/grafana/apps/advisor/pkg/app/checktyperegisterer"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
)
func New(cfg app.Config) (app.App, error) {
// Read config
specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
if !ok {
return nil, fmt.Errorf("invalid config type")
}
checkRegistry := specificConfig.CheckRegistry
// Prepare storage client
clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckKind())
if err != nil {
return nil, err
}
// Initialize checks
checkMap := map[string]checks.Check{}
for _, c := range checkRegistry.Checks() {
checkMap[c.ID()] = c
}
simpleConfig := simple.AppConfig{
Name: "advisor",
KubeConfig: cfg.KubeConfig,
InformerConfig: simple.AppInformerConfig{
ErrorHandler: func(ctx context.Context, err error) {
klog.ErrorS(err, "Informer processing error")
},
},
ManagedKinds: []simple.AppManagedKind{
{
Kind: advisorv0alpha1.CheckKind(),
Validator: &simple.Validator{
ValidateFunc: func(ctx context.Context, req *app.AdmissionRequest) error {
if req.Object != nil {
_, err := getCheck(req.Object, checkMap)
return err
}
return nil
},
},
Watcher: &simple.Watcher{
AddFunc: func(ctx context.Context, obj resource.Object) error {
check, err := getCheck(obj, checkMap)
if err != nil {
return err
}
return processCheck(ctx, client, obj, check)
},
},
},
{
Kind: advisorv0alpha1.CheckTypeKind(),
},
},
}
a, err := simple.NewApp(simpleConfig)
if err != nil {
return nil, err
}
err = a.ValidateManifest(cfg.ManifestData)
if err != nil {
return nil, err
}
// Save check types as resources
ctr, err := checktyperegisterer.New(cfg)
if err != nil {
return nil, err
}
a.AddRunnable(ctr)
// Start scheduler
csch, err := checkscheduler.New(cfg)
if err != nil {
return nil, err
}
a.AddRunnable(csch)
return a, nil
}
func GetKinds() map[schema.GroupVersion][]resource.Kind {
gv := schema.GroupVersion{
// Group and version are the same for all checks
Group: advisorv0alpha1.CheckKind().Group(),
Version: advisorv0alpha1.CheckKind().Version(),
}
return map[schema.GroupVersion][]resource.Kind{
gv: {
advisorv0alpha1.CheckKind(),
advisorv0alpha1.CheckTypeKind(),
},
}
}
-31
View File
@@ -1,31 +0,0 @@
package app
import (
"context"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
func GetAuthorizer() authorizer.Authorizer {
return authorizer.AuthorizerFunc(func(
ctx context.Context, attr authorizer.Attributes,
) (authorized authorizer.Decision, reason string, err error) {
if !attr.IsResourceRequest() {
return authorizer.DecisionNoOpinion, "", nil
}
// require a user
u, err := identity.GetRequester(ctx)
if err != nil {
return authorizer.DecisionDeny, "valid user is required", err
}
// check if is admin
if u.GetIsGrafanaAdmin() {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionDeny, "forbidden", nil
})
}
-78
View File
@@ -1,78 +0,0 @@
package app
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/stretchr/testify/assert"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
func TestGetAuthorizer(t *testing.T) {
tests := []struct {
name string
ctx context.Context
attr authorizer.Attributes
expectedDecision authorizer.Decision
expectedReason string
expectedErr error
}{
{
name: "non-resource request",
ctx: context.TODO(),
attr: &mockAttributes{resourceRequest: false},
expectedDecision: authorizer.DecisionNoOpinion,
expectedReason: "",
expectedErr: nil,
},
{
name: "user is admin",
ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: true}),
attr: &mockAttributes{resourceRequest: true},
expectedDecision: authorizer.DecisionAllow,
expectedReason: "",
expectedErr: nil,
},
{
name: "user is not admin",
ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: false}),
attr: &mockAttributes{resourceRequest: true},
expectedDecision: authorizer.DecisionDeny,
expectedReason: "forbidden",
expectedErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
auth := GetAuthorizer()
decision, reason, err := auth.Authorize(tt.ctx, tt.attr)
assert.Equal(t, tt.expectedDecision, decision)
assert.Equal(t, tt.expectedReason, reason)
assert.Equal(t, tt.expectedErr, err)
})
}
}
type mockAttributes struct {
authorizer.Attributes
resourceRequest bool
}
func (m *mockAttributes) IsResourceRequest() bool {
return m.resourceRequest
}
// Implement other methods of authorizer.Attributes as needed
type mockUser struct {
identity.Requester
isGrafanaAdmin bool
}
func (m *mockUser) GetIsGrafanaAdmin() bool {
return m.isGrafanaAdmin
}
// Implement other methods of identity.Requester as needed
@@ -1,65 +0,0 @@
package checkregistry
import (
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/datasourcecheck"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks/plugincheck"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
)
type CheckService interface {
Checks() []checks.Check
}
type Service struct {
datasourceSvc datasources.DataSourceService
pluginStore pluginstore.Store
pluginContextProvider *plugincontext.Provider
pluginClient plugins.Client
pluginRepo repo.Service
pluginPreinstall plugininstaller.Preinstall
managedPlugins managedplugins.Manager
}
func ProvideService(datasourceSvc datasources.DataSourceService, pluginStore pluginstore.Store,
pluginContextProvider *plugincontext.Provider, pluginClient plugins.Client,
pluginRepo repo.Service, pluginPreinstall plugininstaller.Preinstall, managedPlugins managedplugins.Manager) *Service {
return &Service{
datasourceSvc: datasourceSvc,
pluginStore: pluginStore,
pluginContextProvider: pluginContextProvider,
pluginClient: pluginClient,
pluginRepo: pluginRepo,
pluginPreinstall: pluginPreinstall,
managedPlugins: managedPlugins,
}
}
func (s *Service) Checks() []checks.Check {
return []checks.Check{
datasourcecheck.New(
s.datasourceSvc,
s.pluginStore,
s.pluginContextProvider,
s.pluginClient,
),
plugincheck.New(
s.pluginStore,
s.pluginRepo,
s.pluginPreinstall,
s.managedPlugins,
),
}
}
// AdvisorAppConfig is the configuration received from Grafana to run the app
type AdvisorAppConfig struct {
CheckRegistry CheckService
PluginConfig map[string]string
}
@@ -1,150 +0,0 @@
package datasourcecheck
import (
"context"
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/backend"
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/apimachinery/identity"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/util"
)
type check struct {
DatasourceSvc datasources.DataSourceService
PluginStore pluginstore.Store
PluginContextProvider pluginContextProvider
PluginClient plugins.Client
}
func New(
datasourceSvc datasources.DataSourceService,
pluginStore pluginstore.Store,
pluginContextProvider pluginContextProvider,
pluginClient plugins.Client,
) checks.Check {
return &check{
DatasourceSvc: datasourceSvc,
PluginStore: pluginStore,
PluginContextProvider: pluginContextProvider,
PluginClient: pluginClient,
}
}
func (c *check) Items(ctx context.Context) ([]any, error) {
dss, err := c.DatasourceSvc.GetAllDataSources(ctx, &datasources.GetAllDataSourcesQuery{})
if err != nil {
return nil, err
}
res := make([]any, len(dss))
for i, ds := range dss {
res[i] = ds
}
return res, nil
}
func (c *check) ID() string {
return "datasource"
}
func (c *check) Steps() []checks.Step {
return []checks.Step{
&uidValidationStep{},
&healthCheckStep{
PluginContextProvider: c.PluginContextProvider,
PluginClient: c.PluginClient,
},
}
}
type uidValidationStep struct{}
func (s *uidValidationStep) ID() string {
return "uid-validation"
}
func (s *uidValidationStep) Title() string {
return "UID validation"
}
func (s *uidValidationStep) Description() string {
return "Check if the UID of each data source is valid."
}
func (s *uidValidationStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
ds, ok := i.(*datasources.DataSource)
if !ok {
return nil, fmt.Errorf("invalid item type %T", i)
}
// Data source UID validation
err := util.ValidateUID(ds.UID)
if err != nil {
return checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityLow,
fmt.Sprintf("Invalid UID '%s' for data source %s", ds.UID, ds.Name),
"Check the <a href='https://grafana.com/docs/grafana/latest/upgrade-guide/upgrade-v11.2/#grafana-data-source-uid-format-enforcement' target=_blank>documentation</a> for more information.",
s.ID(),
ds.UID,
), nil
}
return nil, nil
}
type healthCheckStep struct {
PluginContextProvider pluginContextProvider
PluginClient plugins.Client
}
func (s *healthCheckStep) Title() string {
return "Health check"
}
func (s *healthCheckStep) Description() string {
return "Check if all data sources are healthy."
}
func (s *healthCheckStep) ID() string {
return "health-check"
}
func (s *healthCheckStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
ds, ok := i.(*datasources.DataSource)
if !ok {
return nil, fmt.Errorf("invalid item type %T", i)
}
// Health check execution
requester, err := identity.GetRequester(ctx)
if err != nil {
return nil, err
}
pCtx, err := s.PluginContextProvider.GetWithDataSource(ctx, ds.Type, requester, ds)
if err != nil {
return nil, fmt.Errorf("failed to get plugin context: %w", err)
}
req := &backend.CheckHealthRequest{
PluginContext: pCtx,
Headers: map[string]string{},
}
resp, err := s.PluginClient.CheckHealth(ctx, req)
if err != nil || resp.Status != backend.HealthStatusOk {
return checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
fmt.Sprintf("Health check failed for %s", ds.Name),
fmt.Sprintf(
"Go to the <a href='/connections/datasources/edit/%s'>data source configuration</a>"+
" and address the issues reported.", ds.UID),
s.ID(),
ds.UID,
), nil
}
return nil, nil
}
type pluginContextProvider interface {
GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error)
}
@@ -1,149 +0,0 @@
package datasourcecheck
import (
"context"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
)
func TestCheck_Run(t *testing.T) {
t.Run("should return no failures when all datasources are healthy", func(t *testing.T) {
datasources := []*datasources.DataSource{
{UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"},
{UID: "valid-uid-2", Type: "mysql", Name: "MySQL"},
}
mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}}
check := &check{
DatasourceSvc: mockDatasourceSvc,
PluginContextProvider: mockPluginContextProvider,
PluginClient: mockPluginClient,
}
ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
items, err := check.Items(ctx)
assert.NoError(t, err)
failures := []advisor.CheckReportFailure{}
for _, step := range check.Steps() {
for _, item := range items {
stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
assert.NoError(t, err)
if stepFailures != nil {
failures = append(failures, *stepFailures)
}
}
}
assert.NoError(t, err)
assert.Equal(t, 2, len(items))
assert.Empty(t, failures)
})
t.Run("should return failures when datasource UID is invalid", func(t *testing.T) {
datasources := []*datasources.DataSource{
{UID: "invalid uid", Type: "prometheus", Name: "Prometheus"},
}
mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}}
check := &check{
DatasourceSvc: mockDatasourceSvc,
PluginContextProvider: mockPluginContextProvider,
PluginClient: mockPluginClient,
}
ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
items, err := check.Items(ctx)
assert.NoError(t, err)
failures := []advisor.CheckReportFailure{}
for _, step := range check.Steps() {
for _, item := range items {
stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
assert.NoError(t, err)
if stepFailures != nil {
failures = append(failures, *stepFailures)
}
}
}
assert.NoError(t, err)
assert.Equal(t, 1, len(items))
assert.Len(t, failures, 1)
assert.Equal(t, "Invalid UID 'invalid uid' for data source Prometheus", failures[0].Reason)
})
t.Run("should return failures when datasource health check fails", func(t *testing.T) {
datasources := []*datasources.DataSource{
{UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"},
}
mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusError}}
check := &check{
DatasourceSvc: mockDatasourceSvc,
PluginContextProvider: mockPluginContextProvider,
PluginClient: mockPluginClient,
}
ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
items, err := check.Items(ctx)
assert.NoError(t, err)
failures := []advisor.CheckReportFailure{}
for _, step := range check.Steps() {
for _, item := range items {
stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
assert.NoError(t, err)
if stepFailures != nil {
failures = append(failures, *stepFailures)
}
}
}
assert.NoError(t, err)
assert.Equal(t, 1, len(items))
assert.Len(t, failures, 1)
assert.Equal(t, "Health check failed for Prometheus", failures[0].Reason)
})
}
type MockDatasourceSvc struct {
datasources.DataSourceService
dss []*datasources.DataSource
}
func (m *MockDatasourceSvc) GetAllDataSources(ctx context.Context, query *datasources.GetAllDataSourcesQuery) ([]*datasources.DataSource, error) {
return m.dss, nil
}
type MockPluginContextProvider struct {
pCtx backend.PluginContext
}
func (m *MockPluginContextProvider) GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error) {
return m.pCtx, nil
}
type MockPluginClient struct {
plugins.Client
res *backend.CheckHealthResult
}
func (m *MockPluginClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
return m.res, nil
}
-29
View File
@@ -1,29 +0,0 @@
package checks
import (
"context"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
)
// Check returns metadata about the check being executed and the list of Steps
type Check interface {
// ID returns the unique identifier of the check
ID() string
// Items returns the list of items that will be checked
Items(ctx context.Context) ([]any, error)
// Steps returns the list of steps that will be executed
Steps() []Step
}
// Step is a single step in a check, including its metadata
type Step interface {
// ID returns the unique identifier of the step
ID() string
// Title returns the title of the step
Title() string
// Description returns the description of the step
Description() string
// Run executes the step for an item and returns a report
Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error)
}
@@ -1,184 +0,0 @@
package plugincheck
import (
"context"
"fmt"
sysruntime "runtime"
"github.com/Masterminds/semver/v3"
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/cmd/grafana-cli/services"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
)
func New(
pluginStore pluginstore.Store,
pluginRepo repo.Service,
pluginPreinstall plugininstaller.Preinstall,
managedPlugins managedplugins.Manager,
) checks.Check {
return &check{
PluginStore: pluginStore,
PluginRepo: pluginRepo,
PluginPreinstall: pluginPreinstall,
ManagedPlugins: managedPlugins,
}
}
type check struct {
PluginStore pluginstore.Store
PluginRepo repo.Service
PluginPreinstall plugininstaller.Preinstall
ManagedPlugins managedplugins.Manager
}
func (c *check) ID() string {
return "plugin"
}
func (c *check) Items(ctx context.Context) ([]any, error) {
ps := c.PluginStore.Plugins(ctx)
res := make([]any, len(ps))
for i, p := range ps {
res[i] = p
}
return res, nil
}
func (c *check) Steps() []checks.Step {
return []checks.Step{
&deprecationStep{
PluginRepo: c.PluginRepo,
},
&updateStep{
PluginRepo: c.PluginRepo,
PluginPreinstall: c.PluginPreinstall,
ManagedPlugins: c.ManagedPlugins,
},
}
}
type deprecationStep struct {
PluginRepo repo.Service
}
func (s *deprecationStep) Title() string {
return "Deprecation check"
}
func (s *deprecationStep) Description() string {
return "Check if any installed plugins are deprecated."
}
func (s *deprecationStep) ID() string {
return "deprecation"
}
func (s *deprecationStep) Run(ctx context.Context, _ *advisor.CheckSpec, it any) (*advisor.CheckReportFailure, error) {
p, ok := it.(pluginstore.Plugin)
if !ok {
return nil, fmt.Errorf("invalid item type %T", it)
}
// Skip if it's a core plugin
if p.IsCorePlugin() {
return nil, nil
}
// Check if plugin is deprecated
i, err := s.PluginRepo.PluginInfo(ctx, p.ID)
if err != nil {
// Unable to check deprecation status
return nil, nil
}
if i.Status == "deprecated" {
return checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
fmt.Sprintf("Plugin deprecated: %s", p.ID),
"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.",
s.ID(),
p.ID,
), nil
}
return nil, nil
}
type updateStep struct {
PluginRepo repo.Service
PluginPreinstall plugininstaller.Preinstall
ManagedPlugins managedplugins.Manager
}
func (s *updateStep) Title() string {
return "Update check"
}
func (s *updateStep) Description() string {
return "Check if any installed plugins have a newer version available."
}
func (s *updateStep) ID() string {
return "update"
}
func (s *updateStep) Run(ctx context.Context, _ *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
p, ok := i.(pluginstore.Plugin)
if !ok {
return nil, fmt.Errorf("invalid item type %T", i)
}
// Skip if it's a core plugin
if p.IsCorePlugin() {
return nil, nil
}
// Skip if it's managed or pinned
if s.isManaged(ctx, p.ID) || s.PluginPreinstall.IsPinned(p.ID) {
return nil, nil
}
// Check if plugin has a newer version available
compatOpts := repo.NewCompatOpts(services.GrafanaVersion, sysruntime.GOOS, sysruntime.GOARCH)
info, err := s.PluginRepo.GetPluginArchiveInfo(ctx, p.ID, "", compatOpts)
if err != nil {
// Unable to check updates
return nil, nil
}
if hasUpdate(p, info) {
return checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityLow,
fmt.Sprintf("New version available for %s", p.ID),
fmt.Sprintf(
"Go to the <a href='/plugins/%s?page=version-history'>plugin admin page</a>"+
" and upgrade to the latest version.", p.ID),
s.ID(),
p.ID,
), nil
}
return nil, nil
}
func hasUpdate(current pluginstore.Plugin, latest *repo.PluginArchiveInfo) bool {
// If both versions are semver-valid, compare them
v1, err1 := semver.NewVersion(current.Info.Version)
v2, err2 := semver.NewVersion(latest.Version)
if err1 == nil && err2 == nil {
return v1.LessThan(v2)
}
// In other case, assume that a different latest version will always be newer
return current.Info.Version != latest.Version
}
func (s *updateStep) isManaged(ctx context.Context, pluginID string) bool {
for _, managedPlugin := range s.ManagedPlugins.ManagedPlugins(ctx) {
if managedPlugin == pluginID {
return true
}
}
return false
}
@@ -1,198 +0,0 @@
package plugincheck
import (
"context"
"testing"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/stretchr/testify/assert"
)
func TestRun(t *testing.T) {
tests := []struct {
name string
plugins []pluginstore.Plugin
pluginInfo map[string]*repo.PluginInfo
pluginArchives map[string]*repo.PluginArchiveInfo
pluginPreinstalled []string
pluginManaged []string
expectedFailures []advisor.CheckReportFailure
}{
{
name: "No plugins",
plugins: []pluginstore.Plugin{},
expectedFailures: []advisor.CheckReportFailure{},
},
{
name: "Deprecated plugin",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin1", Info: plugins.Info{Version: "1.0.0"}}},
},
pluginInfo: map[string]*repo.PluginInfo{
"plugin1": {Status: "deprecated"},
},
pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin1": {Version: "1.0.0"},
},
expectedFailures: []advisor.CheckReportFailure{
{
Severity: advisor.CheckReportFailureSeverityHigh,
Reason: "Plugin deprecated: plugin1",
Action: "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.",
StepID: "deprecation",
ItemID: "plugin1",
},
},
},
{
name: "Plugin with update",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin2", Info: plugins.Info{Version: "1.0.0"}}},
},
pluginInfo: map[string]*repo.PluginInfo{
"plugin2": {Status: "active"},
},
pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin2": {Version: "1.1.0"},
},
expectedFailures: []advisor.CheckReportFailure{
{
Severity: advisor.CheckReportFailureSeverityLow,
Reason: "New version available for plugin2",
Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.",
StepID: "update",
ItemID: "plugin2",
},
},
},
{
name: "Plugin with update (non semver)",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin2", Info: plugins.Info{Version: "alpha"}}},
},
pluginInfo: map[string]*repo.PluginInfo{
"plugin2": {Status: "active"},
},
pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin2": {Version: "beta"},
},
expectedFailures: []advisor.CheckReportFailure{
{
Severity: advisor.CheckReportFailureSeverityLow,
Reason: "New version available for plugin2",
Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.",
StepID: "update",
ItemID: "plugin2",
},
},
},
{
name: "Plugin pinned",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin3", Info: plugins.Info{Version: "1.0.0"}}},
},
pluginInfo: map[string]*repo.PluginInfo{
"plugin3": {Status: "active"},
},
pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin3": {Version: "1.1.0"},
},
pluginPreinstalled: []string{"plugin3"},
expectedFailures: []advisor.CheckReportFailure{},
},
{
name: "Managed plugin",
plugins: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "plugin4", Info: plugins.Info{Version: "1.0.0"}}},
},
pluginInfo: map[string]*repo.PluginInfo{
"plugin4": {Status: "active"},
},
pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin4": {Version: "1.1.0"},
},
pluginManaged: []string{"plugin4"},
expectedFailures: []advisor.CheckReportFailure{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pluginStore := &mockPluginStore{plugins: tt.plugins}
pluginRepo := &mockPluginRepo{
pluginInfo: tt.pluginInfo,
pluginArchiveInfo: tt.pluginArchives,
}
pluginPreinstall := &mockPluginPreinstall{pinned: tt.pluginPreinstalled}
managedPlugins := &mockManagedPlugins{managed: tt.pluginManaged}
check := New(pluginStore, pluginRepo, pluginPreinstall, managedPlugins)
items, err := check.Items(context.Background())
assert.NoError(t, err)
failures := []advisor.CheckReportFailure{}
for _, step := range check.Steps() {
for _, item := range items {
stepFailures, err := step.Run(context.Background(), &advisor.CheckSpec{}, item)
assert.NoError(t, err)
if stepFailures != nil {
failures = append(failures, *stepFailures)
}
}
}
assert.NoError(t, err)
assert.Equal(t, len(tt.plugins), len(items))
assert.Equal(t, tt.expectedFailures, failures)
})
}
}
type mockPluginStore struct {
pluginstore.Store
plugins []pluginstore.Plugin
}
func (m *mockPluginStore) Plugins(ctx context.Context, t ...plugins.Type) []pluginstore.Plugin {
return m.plugins
}
type mockPluginRepo struct {
repo.Service
pluginInfo map[string]*repo.PluginInfo
pluginArchiveInfo map[string]*repo.PluginArchiveInfo
}
func (m *mockPluginRepo) PluginInfo(ctx context.Context, id string) (*repo.PluginInfo, error) {
return m.pluginInfo[id], nil
}
func (m *mockPluginRepo) GetPluginArchiveInfo(ctx context.Context, id, version string, opts repo.CompatOpts) (*repo.PluginArchiveInfo, error) {
return m.pluginArchiveInfo[id], nil
}
type mockPluginPreinstall struct {
plugininstaller.Preinstall
pinned []string
}
func (m *mockPluginPreinstall) IsPinned(pluginID string) bool {
for _, p := range m.pinned {
if p == pluginID {
return true
}
}
return false
}
type mockManagedPlugins struct {
managedplugins.Manager
managed []string
}
func (m *mockManagedPlugins) ManagedPlugins(ctx context.Context) []string {
return m.managed
}
-26
View File
@@ -1,26 +0,0 @@
package checks
import (
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
)
const (
TypeLabel = "advisor.grafana.app/type"
StatusAnnotation = "advisor.grafana.app/status"
)
func NewCheckReportFailure(
severity advisor.CheckReportFailureSeverity,
reason string,
action string,
stepID string,
itemID string,
) *advisor.CheckReportFailure {
return &advisor.CheckReportFailure{
Severity: severity,
Reason: reason,
Action: action,
StepID: stepID,
ItemID: itemID,
}
}
@@ -1,219 +0,0 @@
package checkscheduler
import (
"context"
"fmt"
"sort"
"strconv"
"time"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/k8s"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
)
const defaultEvaluationInterval = 24 * time.Hour
const defaultMaxHistory = 10
// Runner is a "runnable" app used to be able to expose and API endpoint
// with the existing checks types. This does not need to be a CRUD resource, but it is
// the only way existing at the moment to expose the check types.
type Runner struct {
checkRegistry checkregistry.CheckService
client resource.Client
evaluationInterval time.Duration
maxHistory int
}
// NewRunner creates a new Runner.
func New(cfg app.Config) (app.Runnable, error) {
// Read config
specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
if !ok {
return nil, fmt.Errorf("invalid config type")
}
checkRegistry := specificConfig.CheckRegistry
evalInterval, err := getEvaluationInterval(specificConfig.PluginConfig)
if err != nil {
return nil, err
}
maxHistory, err := getMaxHistory(specificConfig.PluginConfig)
if err != nil {
return nil, err
}
// Prepare storage client
clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckKind())
if err != nil {
return nil, err
}
return &Runner{
checkRegistry: checkRegistry,
client: client,
evaluationInterval: evalInterval,
maxHistory: maxHistory,
}, nil
}
func (r *Runner) Run(ctx context.Context) error {
lastCreated, err := r.checkLastCreated(ctx)
if err != nil {
return err
}
// do an initial creation if necessary
if lastCreated.IsZero() {
err = r.createChecks(ctx)
if err != nil {
klog.Error("Error creating new check reports", "error", err)
} else {
lastCreated = time.Now()
}
}
nextSendInterval := time.Until(lastCreated.Add(r.evaluationInterval))
if nextSendInterval < time.Minute {
nextSendInterval = 1 * time.Minute
}
ticker := time.NewTicker(nextSendInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
err = r.createChecks(ctx)
if err != nil {
klog.Error("Error creating new check reports", "error", err)
}
err = r.cleanupChecks(ctx)
if err != nil {
klog.Error("Error cleaning up old check reports", "error", err)
}
if nextSendInterval != r.evaluationInterval {
nextSendInterval = r.evaluationInterval
}
ticker.Reset(nextSendInterval)
case <-ctx.Done():
return ctx.Err()
}
}
}
// checkLastCreated returns the creation time of the last check created
// regardless of its ID. This assumes that the checks are created in batches
// so a batch will have a similar creation time.
func (r *Runner) checkLastCreated(ctx context.Context) (time.Time, error) {
list, err := r.client.List(ctx, metav1.NamespaceDefault, resource.ListOptions{})
if err != nil {
return time.Time{}, err
}
lastCreated := time.Time{}
for _, item := range list.GetItems() {
itemCreated := item.GetCreationTimestamp().Time
if itemCreated.After(lastCreated) {
lastCreated = itemCreated
}
}
return lastCreated, nil
}
// createChecks creates a new check for each check type in the registry.
func (r *Runner) createChecks(ctx context.Context) error {
for _, check := range r.checkRegistry.Checks() {
obj := &advisorv0alpha1.Check{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "check-",
Namespace: metav1.NamespaceDefault,
Labels: map[string]string{
checks.TypeLabel: check.ID(),
},
},
Spec: advisorv0alpha1.CheckSpec{},
}
id := obj.GetStaticMetadata().Identifier()
_, err := r.client.Create(ctx, id, obj, resource.CreateOptions{})
if err != nil {
return fmt.Errorf("error creating check: %w", err)
}
}
return nil
}
// cleanupChecks deletes the olders checks if the number of checks exceeds the limit.
func (r *Runner) cleanupChecks(ctx context.Context) error {
list, err := r.client.List(ctx, metav1.NamespaceDefault, resource.ListOptions{Limit: -1})
if err != nil {
return err
}
// organize checks by type
checksByType := map[string][]resource.Object{}
for _, check := range list.GetItems() {
labels := check.GetLabels()
checkType, ok := labels[checks.TypeLabel]
if !ok {
klog.Error("Check type not found in labels", "check", check)
continue
}
checksByType[checkType] = append(checksByType[checkType], check)
}
for _, checks := range checksByType {
if len(checks) > r.maxHistory {
// Sort checks by creation time
sort.Slice(checks, func(i, j int) bool {
ti := checks[i].GetCreationTimestamp().Time
tj := checks[j].GetCreationTimestamp().Time
return ti.Before(tj)
})
// Delete the oldest checks
for i := 0; i < len(checks)-r.maxHistory; i++ {
check := checks[i]
id := check.GetStaticMetadata().Identifier()
err := r.client.Delete(ctx, id, resource.DeleteOptions{})
if err != nil {
return fmt.Errorf("error deleting check: %w", err)
}
}
}
}
return nil
}
func getEvaluationInterval(pluginConfig map[string]string) (time.Duration, error) {
evaluationInterval := defaultEvaluationInterval
configEvaluationInterval, ok := pluginConfig["evaluation_interval"]
if ok {
var err error
evaluationInterval, err = gtime.ParseDuration(configEvaluationInterval)
if err != nil {
return 0, fmt.Errorf("invalid evaluation interval: %w", err)
}
}
return evaluationInterval, nil
}
func getMaxHistory(pluginConfig map[string]string) (int, error) {
maxHistory := defaultMaxHistory
configMaxHistory, ok := pluginConfig["max_history"]
if ok {
var err error
maxHistory, err = strconv.Atoi(configMaxHistory)
if err != nil {
return 0, fmt.Errorf("invalid max history: %w", err)
}
}
return maxHistory, nil
}
@@ -1,279 +0,0 @@
package checkscheduler
import (
"context"
"errors"
"fmt"
"math/rand/v2"
"testing"
"time"
"github.com/grafana/grafana-app-sdk/resource"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestRunner_Run_ErrorOnList(t *testing.T) {
mockCheckService := &MockCheckService{}
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return nil, errors.New("list error")
},
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return &advisorv0alpha1.Check{}, nil
},
}
runner := &Runner{
checkRegistry: mockCheckService,
client: mockClient,
}
err := runner.Run(context.Background())
assert.Error(t, err)
}
func TestRunner_checkLastCreated_ErrorOnList(t *testing.T) {
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return nil, errors.New("list error")
},
}
runner := &Runner{
client: mockClient,
}
lastCreated, err := runner.checkLastCreated(context.Background())
assert.Error(t, err)
assert.True(t, lastCreated.IsZero())
}
func TestRunner_createChecks_ErrorOnCreate(t *testing.T) {
mockCheckService := &MockCheckService{
checks: []checks.Check{
&mockCheck{
id: "check-1",
},
},
}
mockClient := &MockClient{
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return nil, errors.New("create error")
},
}
runner := &Runner{
checkRegistry: mockCheckService,
client: mockClient,
}
err := runner.createChecks(context.Background())
assert.Error(t, err)
}
func TestRunner_createChecks_Success(t *testing.T) {
mockCheckService := &MockCheckService{
checks: []checks.Check{
&mockCheck{
id: "check-1",
},
},
}
mockClient := &MockClient{
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return &advisorv0alpha1.Check{}, nil
},
}
runner := &Runner{
checkRegistry: mockCheckService,
client: mockClient,
}
err := runner.createChecks(context.Background())
assert.NoError(t, err)
}
func TestRunner_cleanupChecks_ErrorOnList(t *testing.T) {
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return nil, errors.New("list error")
},
}
runner := &Runner{
client: mockClient,
}
err := runner.cleanupChecks(context.Background())
assert.Error(t, err)
}
func TestRunner_cleanupChecks_WithinMax(t *testing.T) {
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return &advisorv0alpha1.CheckList{
Items: []advisorv0alpha1.Check{{}, {}},
}, nil
},
deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
return fmt.Errorf("shouldn't be called")
},
}
runner := &Runner{
client: mockClient,
}
err := runner.cleanupChecks(context.Background())
assert.NoError(t, err)
}
func TestRunner_cleanupChecks_ErrorOnDelete(t *testing.T) {
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1)
for i := 0; i < defaultMaxHistory+1; i++ {
item := advisorv0alpha1.Check{}
item.ObjectMeta.SetLabels(map[string]string{
checks.TypeLabel: "mock",
})
items = append(items, item)
}
return &advisorv0alpha1.CheckList{
Items: items,
}, nil
},
deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
return errors.New("delete error")
},
}
runner := &Runner{
client: mockClient,
maxHistory: defaultMaxHistory,
}
err := runner.cleanupChecks(context.Background())
assert.ErrorContains(t, err, "delete error")
}
func TestRunner_cleanupChecks_Success(t *testing.T) {
itemsDeleted := []string{}
items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1)
for i := 0; i < defaultMaxHistory+1; i++ {
item := advisorv0alpha1.Check{}
item.ObjectMeta.SetName(fmt.Sprintf("check-%d", i))
item.ObjectMeta.SetLabels(map[string]string{
checks.TypeLabel: "mock",
})
item.ObjectMeta.SetCreationTimestamp(metav1.NewTime(time.Time{}.Add(time.Duration(i) * time.Hour)))
items = append(items, item)
}
// shuffle the items to ensure the oldest are deleted
rand.Shuffle(len(items), func(i, j int) { items[i], items[j] = items[j], items[i] })
mockClient := &MockClient{
listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return &advisorv0alpha1.CheckList{
Items: items,
}, nil
},
deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
itemsDeleted = append(itemsDeleted, identifier.Name)
return nil
},
}
runner := &Runner{
client: mockClient,
maxHistory: defaultMaxHistory,
}
err := runner.cleanupChecks(context.Background())
assert.NoError(t, err)
assert.Equal(t, []string{"check-0"}, itemsDeleted)
}
func Test_getEvaluationInterval(t *testing.T) {
t.Run("default", func(t *testing.T) {
interval, err := getEvaluationInterval(map[string]string{})
assert.NoError(t, err)
assert.Equal(t, 24*time.Hour, interval)
})
t.Run("invalid", func(t *testing.T) {
interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "invalid"})
assert.Error(t, err)
assert.Zero(t, interval)
})
t.Run("custom", func(t *testing.T) {
interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "1h"})
assert.NoError(t, err)
assert.Equal(t, time.Hour, interval)
})
}
func Test_getMaxHistory(t *testing.T) {
t.Run("default", func(t *testing.T) {
history, err := getMaxHistory(map[string]string{})
assert.NoError(t, err)
assert.Equal(t, 10, history)
})
t.Run("invalid", func(t *testing.T) {
history, err := getMaxHistory(map[string]string{"max_history": "invalid"})
assert.Error(t, err)
assert.Zero(t, history)
})
t.Run("custom", func(t *testing.T) {
history, err := getMaxHistory(map[string]string{"max_history": "5"})
assert.NoError(t, err)
assert.Equal(t, 5, history)
})
}
type MockCheckService struct {
checks []checks.Check
}
func (m *MockCheckService) Checks() []checks.Check {
return m.checks
}
type MockClient struct {
resource.Client
listFunc func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error)
createFunc func(ctx context.Context, identifier resource.Identifier, obj resource.Object, options resource.CreateOptions) (resource.Object, error)
deleteFunc func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error
}
func (m *MockClient) List(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
return m.listFunc(ctx, namespace, options)
}
func (m *MockClient) Create(ctx context.Context, identifier resource.Identifier, obj resource.Object, options resource.CreateOptions) (resource.Object, error) {
return m.createFunc(ctx, identifier, obj, options)
}
func (m *MockClient) Delete(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
return m.deleteFunc(ctx, identifier, options)
}
type mockCheck struct {
checks.Check
id string
steps []checks.Step
}
func (m *mockCheck) ID() string {
return m.id
}
func (m *mockCheck) Steps() []checks.Step {
return m.steps
}
@@ -1,83 +0,0 @@
package checktyperegisterer
import (
"context"
"fmt"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/k8s"
"github.com/grafana/grafana-app-sdk/resource"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// Runner is a "runnable" app used to be able to expose and API endpoint
// with the existing checks types. This does not need to be a CRUD resource, but it is
// the only way existing at the moment to expose the check types.
type Runner struct {
checkRegistry checkregistry.CheckService
client resource.Client
}
// NewRunner creates a new Runner.
func New(cfg app.Config) (app.Runnable, error) {
// Read config
specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
if !ok {
return nil, fmt.Errorf("invalid config type")
}
checkRegistry := specificConfig.CheckRegistry
// Prepare storage client
clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckTypeKind())
if err != nil {
return nil, err
}
return &Runner{
checkRegistry: checkRegistry,
client: client,
}, nil
}
func (r *Runner) Run(ctx context.Context) error {
for _, t := range r.checkRegistry.Checks() {
steps := t.Steps()
stepTypes := make([]advisorv0alpha1.CheckTypeStep, len(steps))
for i, s := range steps {
stepTypes[i] = advisorv0alpha1.CheckTypeStep{
Title: s.Title(),
Description: s.Description(),
StepID: s.ID(),
}
}
obj := &advisorv0alpha1.CheckType{
ObjectMeta: metav1.ObjectMeta{
Name: t.ID(),
Namespace: metav1.NamespaceDefault,
},
Spec: advisorv0alpha1.CheckTypeSpec{
Name: t.ID(),
Steps: stepTypes,
},
}
id := obj.GetStaticMetadata().Identifier()
_, err := r.client.Create(ctx, id, obj, resource.CreateOptions{})
if err != nil {
if errors.IsAlreadyExists(err) {
// Already exists, update
_, err = r.client.Update(ctx, id, obj, resource.UpdateOptions{})
if err != nil {
return err
} else {
continue
}
}
return err
}
}
return nil
}
@@ -1,169 +0,0 @@
package checktyperegisterer
import (
"context"
"errors"
"testing"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
k8sErrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestCheckTypesRegisterer_Run(t *testing.T) {
tests := []struct {
name string
checks []checks.Check
createFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error)
updateFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error)
expectedErr error
}{
{
name: "successful create",
checks: []checks.Check{
&mockCheck{
id: "check1",
steps: []checks.Step{
&mockStep{id: "step1", title: "Step 1", description: "Description 1"},
},
},
},
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return obj, nil
},
updateFunc: nil,
expectedErr: nil,
},
{
name: "create already exists, successful update",
checks: []checks.Check{
&mockCheck{
id: "check1",
steps: []checks.Step{
&mockStep{id: "step1", title: "Step 1", description: "Description 1"},
},
},
},
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return nil, k8sErrs.NewAlreadyExists(schema.GroupResource{}, obj.GetName())
},
updateFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
return obj, nil
},
expectedErr: nil,
},
{
name: "create error",
checks: []checks.Check{
&mockCheck{
id: "check1",
steps: []checks.Step{
&mockStep{id: "step1", title: "Step 1", description: "Description 1"},
},
},
},
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return nil, errors.New("create error")
},
updateFunc: nil,
expectedErr: errors.New("create error"),
},
{
name: "update error",
checks: []checks.Check{
&mockCheck{
id: "check1",
steps: []checks.Step{
&mockStep{id: "step1", title: "Step 1", description: "Description 1"},
},
},
},
createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return nil, k8sErrs.NewAlreadyExists(schema.GroupResource{}, obj.GetName())
},
updateFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
return nil, errors.New("update error")
},
expectedErr: errors.New("update error"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Runner{
checkRegistry: &mockCheckRegistry{checks: tt.checks},
client: &mockClient{
createFunc: tt.createFunc,
updateFunc: tt.updateFunc,
},
}
err := r.Run(context.Background())
if err != nil {
if tt.expectedErr == nil {
t.Errorf("unexpected error: %v", err)
} else if err.Error() != tt.expectedErr.Error() {
t.Errorf("expected error: %v, got: %v", tt.expectedErr, err)
}
}
})
}
}
type mockCheckRegistry struct {
checks []checks.Check
}
func (m *mockCheckRegistry) Checks() []checks.Check {
return m.checks
}
type mockCheck struct {
checks.Check
id string
steps []checks.Step
}
func (m *mockCheck) ID() string {
return m.id
}
func (m *mockCheck) Steps() []checks.Step {
return m.steps
}
type mockStep struct {
checks.Step
id string
title string
description string
}
func (m *mockStep) ID() string {
return m.id
}
func (m *mockStep) Title() string {
return m.title
}
func (m *mockStep) Description() string {
return m.description
}
type mockClient struct {
resource.Client
createFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error)
updateFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error)
}
func (m *mockClient) Create(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
return m.createFunc(ctx, id, obj, opts)
}
func (m *mockClient) Update(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
return m.updateFunc(ctx, id, obj, opts)
}
-143
View File
@@ -1,143 +0,0 @@
package app
import (
"context"
"errors"
"fmt"
"sync"
claims "github.com/grafana/authlib/types"
"github.com/grafana/grafana-app-sdk/resource"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/services/user"
)
func getCheck(obj resource.Object, checkMap map[string]checks.Check) (checks.Check, error) {
labels := obj.GetLabels()
objTypeLabel, ok := labels[checks.TypeLabel]
if !ok {
return nil, errors.New("missing check type as label")
}
c, ok := checkMap[objTypeLabel]
if !ok {
supportedTypes := ""
for k := range checkMap {
supportedTypes += k + ", "
}
return nil, fmt.Errorf("unknown check type %s. Supported types are: %s", objTypeLabel, supportedTypes)
}
return c, nil
}
func getStatusAnnotation(obj resource.Object) string {
return obj.GetAnnotations()[checks.StatusAnnotation]
}
func setStatusAnnotation(ctx context.Context, client resource.Client, obj resource.Object, status string) error {
annotations := obj.GetAnnotations()
annotations[checks.StatusAnnotation] = status
return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
Operations: []resource.PatchOperation{{
Operation: resource.PatchOpAdd,
Path: "/metadata/annotations",
Value: annotations,
}},
}, resource.PatchOptions{}, obj)
}
func processCheck(ctx context.Context, client resource.Client, obj resource.Object, check checks.Check) error {
status := getStatusAnnotation(obj)
if status != "" {
// Check already processed
return nil
}
c, ok := obj.(*advisorv0alpha1.Check)
if !ok {
return fmt.Errorf("invalid object type")
}
// Populate ctx with the user that created the check
meta, err := utils.MetaAccessor(obj)
if err != nil {
return err
}
createdBy := meta.GetCreatedBy()
typ, uid, err := claims.ParseTypeID(createdBy)
if err != nil {
return err
}
ctx = identity.WithRequester(ctx, &user.SignedInUser{
UserUID: uid,
FallbackType: typ,
})
// Get the items to check
items, err := check.Items(ctx)
if err != nil {
setErr := setStatusAnnotation(ctx, client, obj, "error")
if setErr != nil {
return setErr
}
return fmt.Errorf("error initializing check: %w", err)
}
// Run the steps
steps := check.Steps()
failures, err := runStepsInParallel(ctx, &c.Spec, steps, items)
if err != nil {
setErr := setStatusAnnotation(ctx, client, obj, "error")
if setErr != nil {
return setErr
}
return fmt.Errorf("error running steps: %w", err)
}
report := &advisorv0alpha1.CheckV0alpha1StatusReport{
Failures: failures,
Count: int64(len(items)),
}
err = setStatusAnnotation(ctx, client, obj, "processed")
if err != nil {
return err
}
return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
Operations: []resource.PatchOperation{{
Operation: resource.PatchOpAdd,
Path: "/status/report",
Value: *report,
}},
}, resource.PatchOptions{}, obj)
}
func runStepsInParallel(ctx context.Context, spec *advisorv0alpha1.CheckSpec, steps []checks.Step, items []any) ([]advisorv0alpha1.CheckReportFailure, error) {
reportFailures := []advisorv0alpha1.CheckReportFailure{}
var internalErr error
var wg sync.WaitGroup
var mu sync.Mutex
// Avoid too many concurrent requests
limit := make(chan struct{}, 10)
for _, step := range steps {
for _, item := range items {
wg.Add(1)
limit <- struct{}{}
go func(step checks.Step, item any) {
defer wg.Done()
defer func() { <-limit }()
stepErr, err := step.Run(ctx, spec, item)
mu.Lock()
defer mu.Unlock()
if err != nil {
internalErr = fmt.Errorf("error running step %s: %w", step.ID(), err)
return
}
if stepErr != nil {
reportFailures = append(reportFailures, *stepErr)
}
}(step, item)
}
}
wg.Wait()
return reportFailures, internalErr
}
-196
View File
@@ -1,196 +0,0 @@
package app
import (
"context"
"errors"
"fmt"
"testing"
"github.com/grafana/grafana-app-sdk/resource"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/stretchr/testify/assert"
)
func TestGetCheck(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetLabels(map[string]string{checks.TypeLabel: "testType"})
checkMap := map[string]checks.Check{
"testType": &mockCheck{},
}
check, err := getCheck(obj, checkMap)
assert.NoError(t, err)
assert.NotNil(t, check)
}
func TestGetCheck_MissingLabel(t *testing.T) {
obj := &advisorv0alpha1.Check{}
checkMap := map[string]checks.Check{}
_, err := getCheck(obj, checkMap)
assert.Error(t, err)
assert.Equal(t, "missing check type as label", err.Error())
}
func TestGetCheck_UnknownType(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetLabels(map[string]string{checks.TypeLabel: "unknownType"})
checkMap := map[string]checks.Check{
"testType": &mockCheck{},
}
_, err := getCheck(obj, checkMap)
assert.Error(t, err)
assert.Contains(t, err.Error(), "unknown check type unknownType")
}
func TestSetStatusAnnotation(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetAnnotations(map[string]string{})
client := &mockClient{}
ctx := context.TODO()
err := setStatusAnnotation(ctx, client, obj, "processed")
assert.NoError(t, err)
assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
}
func TestProcessCheck(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetAnnotations(map[string]string{})
meta, err := utils.MetaAccessor(obj)
if err != nil {
t.Fatal(err)
}
meta.SetCreatedBy("user:1")
client := &mockClient{}
ctx := context.TODO()
check := &mockCheck{
items: []any{"item"},
}
err = processCheck(ctx, client, obj, check)
assert.NoError(t, err)
assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
}
func TestProcessMultipleCheckItems(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetAnnotations(map[string]string{})
meta, err := utils.MetaAccessor(obj)
if err != nil {
t.Fatal(err)
}
meta.SetCreatedBy("user:1")
client := &mockClient{}
ctx := context.TODO()
items := make([]any, 100)
for i := range items {
if i%2 == 0 {
items[i] = fmt.Sprintf("item-%d", i)
} else {
items[i] = errors.New("error")
}
}
check := &mockCheck{
items: items,
}
err = processCheck(ctx, client, obj, check)
assert.NoError(t, err)
assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
r := client.lastValue.(advisorv0alpha1.CheckV0alpha1StatusReport)
assert.Equal(t, r.Count, int64(100))
assert.Len(t, r.Failures, 50)
}
func TestProcessCheck_AlreadyProcessed(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetAnnotations(map[string]string{checks.StatusAnnotation: "processed"})
client := &mockClient{}
ctx := context.TODO()
check := &mockCheck{}
err := processCheck(ctx, client, obj, check)
assert.NoError(t, err)
}
func TestProcessCheck_RunError(t *testing.T) {
obj := &advisorv0alpha1.Check{}
obj.SetAnnotations(map[string]string{})
meta, err := utils.MetaAccessor(obj)
if err != nil {
t.Fatal(err)
}
meta.SetCreatedBy("user:1")
client := &mockClient{}
ctx := context.TODO()
check := &mockCheck{
items: []any{"item"},
err: errors.New("run error"),
}
err = processCheck(ctx, client, obj, check)
assert.Error(t, err)
assert.Equal(t, "error", obj.GetAnnotations()[checks.StatusAnnotation])
}
type mockClient struct {
resource.Client
lastValue any
}
func (m *mockClient) PatchInto(ctx context.Context, id resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions, obj resource.Object) error {
m.lastValue = req.Operations[0].Value
return nil
}
type mockCheck struct {
err error
items []any
}
func (m *mockCheck) ID() string {
return "mock"
}
func (m *mockCheck) Items(ctx context.Context) ([]any, error) {
return m.items, nil
}
func (m *mockCheck) Steps() []checks.Step {
return []checks.Step{
&mockStep{err: m.err},
}
}
type mockStep struct {
err error
}
func (m *mockStep) Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, items any) (*advisorv0alpha1.CheckReportFailure, error) {
if m.err != nil {
return nil, m.err
}
if _, ok := items.(error); ok {
return &advisorv0alpha1.CheckReportFailure{}, nil
}
return nil, nil
}
func (m *mockStep) Title() string {
return "mock"
}
func (m *mockStep) Description() string {
return "mock"
}
func (m *mockStep) ID() string {
return "mock"
}
-7
View File
@@ -1,7 +0,0 @@
This folder contains the automatically generated types for the frontend that are used in the app plugin.
To update the types:
1. Make any necessary changes in the `kinds` directory
2. Run `make generate`
3. Copy the `plugin` directory to the frontend app: https://github.com/grafana/grafana-advisor-app/tree/main/src/plugin
+17 -17
View File
@@ -1,14 +1,14 @@
module github.com/grafana/grafana/apps/alerting/notifications
go 1.23.5
go 1.23.7
replace github.com/grafana/grafana => ../../..
require (
github.com/grafana/grafana v11.4.0-00010101000000-000000000000+incompatible
github.com/grafana/grafana-app-sdk v0.31.0
k8s.io/apimachinery v0.32.1
k8s.io/apiserver v0.32.1
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
github.com/grafana/grafana-app-sdk v0.23.1
k8s.io/apimachinery v0.32.0
k8s.io/apiserver v0.32.0
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -36,9 +36,9 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d // indirect
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath-community/go-jmespath v1.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
@@ -52,10 +52,10 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/common v0.61.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
@@ -72,13 +72,13 @@ require (
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
@@ -87,9 +87,9 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.1 // indirect
k8s.io/client-go v0.32.1 // indirect
k8s.io/component-base v0.32.1 // indirect
k8s.io/api v0.32.0 // indirect
k8s.io/client-go v0.32.0 // indirect
k8s.io/component-base v0.32.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
+30 -29
View File
@@ -71,18 +71,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/grafana-app-sdk v0.31.0 h1:/mFCcx+YqG8cWAi9hePDJQxIdtXDClDIDRgZwHkksFk=
github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d h1:0WJ4uZ3gtbX7S5RGMarA+0TccmB7qEPhhNm34NcfBzs=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d/go.mod h1:PNmbi49lVrv2b2I8pdu46dTs2728lKEbnVuQD8I5MnM=
github.com/grafana/grafana-app-sdk v0.23.1 h1:BRpUG0bA0oVxjthkmO2thuJBo3nbjaRSSmZJHw+mA8I=
github.com/grafana/grafana-app-sdk v0.23.1/go.mod h1:KzgPnTJfMeckGmMctv6CJb8Jr/o/5rwARDyjXoeR0Fc=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da h1:2E3c/I3ayAy4Z1GwIPqXNZcpUccRapE1aBXA1ho4g7o=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240821155123-6891eb1d35da/go.mod h1:p09fvU5ujNL/Ig8HB7g4f+S0zyYbQq3x/f0jA4ujVOM=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath-community/go-jmespath v1.1.1 h1:bFikPhsi/FdmlZhVgSCd2jj1e7G/rw+zyQfyg5UF+L4=
@@ -130,8 +130,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
@@ -144,8 +144,9 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -207,8 +208,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -223,11 +224,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -239,12 +240,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -283,16 +284,16 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
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=
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apiserver v0.32.1 h1:oo0OozRos66WFq87Zc5tclUX2r0mymoVHRq8JmR7Aak=
k8s.io/apiserver v0.32.1/go.mod h1:UcB9tWjBY7aryeI5zAgzVJB/6k7E97bkr1RgqDz0jPw=
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk=
k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w=
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs=
k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
+3
View File
@@ -0,0 +1,3 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --kindgrouping=group --postprocess --crdencoding none
@@ -1,10 +1,10 @@
module github.com/grafana/grafana/apps/investigations
module github.com/grafana/grafana/apps/investigation
go 1.23.4
go 1.23.7
require (
github.com/grafana/grafana-app-sdk v0.31.0
k8s.io/apimachinery v0.32.1
github.com/grafana/grafana-app-sdk v0.23.1
k8s.io/apimachinery v0.32.0
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -18,7 +18,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/getkin/kin-openapi v0.129.0 // indirect
github.com/getkin/kin-openapi v0.128.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -29,12 +29,11 @@ require (
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
@@ -43,31 +42,28 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/common v0.61.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
@@ -76,9 +72,9 @@ require (
google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.1 // indirect
k8s.io/apiextensions-apiserver v0.32.1 // indirect
k8s.io/client-go v0.32.1 // indirect
k8s.io/api v0.32.0 // indirect
k8s.io/apiextensions-apiserver v0.32.0 // indirect
k8s.io/client-go v0.32.0 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
@@ -16,8 +16,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4=
github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -29,8 +29,6 @@ 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/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-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-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -45,21 +43,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
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-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.31.0 h1:/mFCcx+YqG8cWAi9hePDJQxIdtXDClDIDRgZwHkksFk=
github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
github.com/grafana/grafana-app-sdk/logging v0.30.0 h1:K/P/bm7Cp7Di4tqIJ3EQz2+842JozQGRaz62r95ApME=
github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grafana/grafana-app-sdk v0.23.1 h1:BRpUG0bA0oVxjthkmO2thuJBo3nbjaRSSmZJHw+mA8I=
github.com/grafana/grafana-app-sdk v0.23.1/go.mod h1:KzgPnTJfMeckGmMctv6CJb8Jr/o/5rwARDyjXoeR0Fc=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
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/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/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -85,14 +81,6 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
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/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -104,16 +92,16 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
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/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/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -132,8 +120,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glB
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
@@ -155,34 +143,30 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -206,14 +190,14 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw=
k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
@@ -0,0 +1,2 @@
module: "github.com/grafana/grafana/apps/investigation/kinds"
language: version: "v0.8.2"
@@ -0,0 +1,96 @@
package kinds
// This is our Investigation definition, which contains metadata about the kind, and the kind's schema
investigation: {
group: "investigation"
kind: "Investigation"
pluralName: "Investigations"
scope: "Namespaced"
apiResource: {
groupOverride: "investigation.grafana.app"
}
codegen: {
frontend: false
backend: true
}
current: "v1alpha1"
versions: {
"v1alpha1": {
version: "v1alpha1"
schema: {
// spec is the schema of our resource. The spec should include all the user-ediable information for the kind.
spec: #InvestigationSpec
}
}
}
}
#InvestigationSpec: {
title: string
status: "open" | "closed"
items: [...#InvestigationItem]
}
// InvestigationItem is an item in an investigation.
#InvestigationItem: {
id: string
title: string
// type is the type of the item "timeseries", "heatmap", "log-table" (not an enum to allow for future extensions).
type: string
// url is the URL to the item.
url: string
// origin is where the item was created from.
origin: string // "explore-metrics", "explore-logs", "explore-traces" (not an enum to allow for future extensions)
// iconPath (optional) is the path to the icon for the item.
iconPath?: string
// timeRange (optional) is the time range of the item.
timeRange: #AbsoluteTimeRange
// note (optional) is a comment on the item.
note?: [...#Comment]
// queryType is the type of the query used to generate this item.
queryType: "logs" | "metrics"
// dataQuery contains the query used to generate this item.
dataQuery: #DataQueryLogs | #DataQueryMetrics
}
// DataQueryLogs is a data query for logs.
#DataQueryLogs: {
// refId is the reference ID of the query.
refId: string
// datasource is the datasource of the query.
datasource: #DatasourceRef
// expr is the expression of the query.
expr: string
// maxLines (optional) is used to limit the number of log rows returned.
maxLines?: int64
}
// DataQueryMetrics is a data query for metrics.
#DataQueryMetrics: {
refId: string
datasource: #DatasourceRef
expr: string
}
// Comment is a comment on an investigation item.
#Comment: {
authorUserID: string
bodyMarkdown: string
}
// DatasourceRef is a reference to a datasource.
#DatasourceRef: {
uid: string
type: string
apiVersion: string
name: string
}
// AbsoluteTimeRange is a time range specified by absolute timestamps.
#AbsoluteTimeRange: {
from: number
to: number
}
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
package v1alpha1
import (
"encoding/json"
@@ -0,0 +1,32 @@
package v1alpha1
import (
"time"
)
// InvestigationMetadata defines model for InvestigationMetadata.
type InvestigationMetadata struct {
CreatedBy string `json:"createdBy"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
Generation int64 `json:"generation"`
Labels map[string]string `json:"labels"`
ResourceVersion string `json:"resourceVersion"`
Uid string `json:"uid"`
UpdateTimestamp time.Time `json:"updateTimestamp"`
UpdatedBy string `json:"updatedBy"`
}
// _kubeObjectMetadata is metadata found in a kubernetes object's metadata field.
// It is not exhaustive and only includes fields which may be relevant to a kind's implementation,
// As it is also intended to be generic enough to function with any API Server.
type InvestigationKubeObjectMetadata struct {
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
Generation int64 `json:"generation"`
Labels map[string]string `json:"labels"`
ResourceVersion string `json:"resourceVersion"`
Uid string `json:"uid"`
}
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
package v1alpha1
import (
"fmt"
@@ -16,10 +16,10 @@ import (
// +k8s:openapi-gen=true
type Investigation struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
Spec InvestigationSpec `json:"spec" yaml:"spec"`
InvestigationStatus InvestigationStatus `json:"status" yaml:"status"`
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec InvestigationSpec `json:"spec"`
InvestigationStatus InvestigationStatus `json:"status"`
}
func (o *Investigation) GetSpec() any {
@@ -224,9 +224,9 @@ var _ resource.Object = &Investigation{}
// +k8s:openapi-gen=true
type InvestigationList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []Investigation `json:"items" yaml:"items"`
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Investigation `json:"items"`
}
func (o *InvestigationList) DeepCopyObject() runtime.Object {
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
package v1alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaInvestigation = resource.NewSimpleSchema("investigations.grafana.app", "v0alpha1", &Investigation{}, &InvestigationList{}, resource.WithKind("Investigation"),
schemaInvestigation = resource.NewSimpleSchema("investigation.grafana.app", "v1alpha1", &Investigation{}, &InvestigationList{}, resource.WithKind("Investigation"),
resource.WithPlural("investigations"), resource.WithScope(resource.NamespacedScope))
kindInvestigation = resource.Kind{
Schema: schemaInvestigation,
@@ -0,0 +1,107 @@
package v1alpha1
// Defines values for InvestigationInvestigationItemQueryType.
const (
InvestigationInvestigationItemQueryTypeLogs InvestigationInvestigationItemQueryType = "logs"
InvestigationInvestigationItemQueryTypeMetrics InvestigationInvestigationItemQueryType = "metrics"
)
// Defines values for InvestigationSpecStatus.
const (
InvestigationSpecStatusClosed InvestigationSpecStatus = "closed"
InvestigationSpecStatusOpen InvestigationSpecStatus = "open"
)
// AbsoluteTimeRange is a time range specified by absolute timestamps.
// +k8s:openapi-gen=true
type InvestigationAbsoluteTimeRange struct {
From float32 `json:"from"`
To float32 `json:"to"`
}
// Comment is a comment on an investigation item.
// +k8s:openapi-gen=true
type InvestigationComment struct {
AuthorUserID string `json:"authorUserID"`
BodyMarkdown string `json:"bodyMarkdown"`
}
// DataQueryLogs is a data query for logs.
// +k8s:openapi-gen=true
type InvestigationDataQueryLogs struct {
// DatasourceRef is a reference to a datasource.
Datasource InvestigationDatasourceRef `json:"datasource"`
// expr is the expression of the query.
Expr string `json:"expr"`
// maxLines (optional) is used to limit the number of log rows returned.
MaxLines *int64 `json:"maxLines,omitempty"`
// refId is the reference ID of the query.
RefId string `json:"refId"`
}
// DataQueryMetrics is a data query for metrics.
// +k8s:openapi-gen=true
type InvestigationDataQueryMetrics struct {
// DatasourceRef is a reference to a datasource.
Datasource InvestigationDatasourceRef `json:"datasource"`
Expr string `json:"expr"`
RefId string `json:"refId"`
}
// DatasourceRef is a reference to a datasource.
// +k8s:openapi-gen=true
type InvestigationDatasourceRef struct {
ApiVersion string `json:"apiVersion"`
Name string `json:"name"`
Type string `json:"type"`
Uid string `json:"uid"`
}
// InvestigationItem is an item in an investigation.
// +k8s:openapi-gen=true
type InvestigationInvestigationItem struct {
// dataQuery contains the query used to generate this item.
DataQuery interface{} `json:"dataQuery"`
// iconPath (optional) is the path to the icon for the item.
IconPath *string `json:"iconPath,omitempty"`
Id string `json:"id"`
// note (optional) is a comment on the item.
Note []InvestigationComment `json:"note,omitempty"`
// origin is where the item was created from.
Origin string `json:"origin"`
// queryType is the type of the query used to generate this item.
QueryType InvestigationInvestigationItemQueryType `json:"queryType"`
// AbsoluteTimeRange is a time range specified by absolute timestamps.
TimeRange InvestigationAbsoluteTimeRange `json:"timeRange"`
Title string `json:"title"`
// type is the type of the item "timeseries", "heatmap", "log-table" (not an enum to allow for future extensions).
Type string `json:"type"`
// url is the URL to the item.
Url string `json:"url"`
}
// InvestigationInvestigationItemQueryType queryType is the type of the query used to generate this item.
// +k8s:openapi-gen=true
type InvestigationInvestigationItemQueryType string
// InvestigationSpec defines model for InvestigationSpec.
// +k8s:openapi-gen=true
type InvestigationSpec struct {
Items []InvestigationInvestigationItem `json:"items"`
Status InvestigationSpecStatus `json:"status"`
Title string `json:"title"`
}
// InvestigationSpecStatus defines model for InvestigationSpec.Status.
// +k8s:openapi-gen=true
type InvestigationSpecStatus string
@@ -0,0 +1,70 @@
package v1alpha1
// Defines values for InvestigationOperatorStateState.
const (
InvestigationOperatorStateStateFailed InvestigationOperatorStateState = "failed"
InvestigationOperatorStateStateInProgress InvestigationOperatorStateState = "in_progress"
InvestigationOperatorStateStateSuccess InvestigationOperatorStateState = "success"
)
// Defines values for InvestigationstatusOperatorStateState.
const (
InvestigationstatusOperatorStateStateFailed InvestigationstatusOperatorStateState = "failed"
InvestigationstatusOperatorStateStateInProgress InvestigationstatusOperatorStateState = "in_progress"
InvestigationstatusOperatorStateStateSuccess InvestigationstatusOperatorStateState = "success"
)
// InvestigationOperatorState defines model for InvestigationOperatorState.
// +k8s:openapi-gen=true
type InvestigationOperatorState struct {
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State InvestigationOperatorStateState `json:"state"`
}
// InvestigationOperatorStateState state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
// +k8s:openapi-gen=true
type InvestigationOperatorStateState string
// InvestigationStatus defines model for InvestigationStatus.
// +k8s:openapi-gen=true
type InvestigationStatus struct {
// additionalFields is reserved for future use
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]InvestigationstatusOperatorState `json:"operatorStates,omitempty"`
}
// InvestigationstatusOperatorState defines model for Investigationstatus.#OperatorState.
// +k8s:openapi-gen=true
type InvestigationstatusOperatorState struct {
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State InvestigationstatusOperatorStateState `json:"state"`
}
// InvestigationstatusOperatorStateState state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
// +k8s:openapi-gen=true
type InvestigationstatusOperatorStateState string
@@ -3,7 +3,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
package v0alpha1
package v1alpha1
import (
common "k8s.io/kube-openapi/pkg/common"
@@ -12,23 +12,22 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure": schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType": schema_pkg_apis_advisor_v0alpha1_CheckType(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeList": schema_pkg_apis_advisor_v0alpha1_CheckTypeList(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec": schema_pkg_apis_advisor_v0alpha1_CheckTypeSpec(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus": schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep": schema_pkg_apis_advisor_v0alpha1_CheckTypeStep(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation": schema_pkg_apis_investigation_v1alpha1_Investigation(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange": schema_pkg_apis_investigation_v1alpha1_InvestigationAbsoluteTimeRange(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment": schema_pkg_apis_investigation_v1alpha1_InvestigationComment(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDataQueryLogs": schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryLogs(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDataQueryMetrics": schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryMetrics(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef": schema_pkg_apis_investigation_v1alpha1_InvestigationDatasourceRef(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem": schema_pkg_apis_investigation_v1alpha1_InvestigationInvestigationItem(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationList": schema_pkg_apis_investigation_v1alpha1_InvestigationList(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationOperatorState": schema_pkg_apis_investigation_v1alpha1_InvestigationOperatorState(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec": schema_pkg_apis_investigation_v1alpha1_InvestigationSpec(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus": schema_pkg_apis_investigation_v1alpha1_InvestigationStatus(ref),
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState": schema_pkg_apis_investigation_v1alpha1_InvestigationstatusOperatorState(ref),
}
}
func schema_pkg_apis_advisor_v0alpha1_Check(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_investigation_v1alpha1_Investigation(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@@ -57,13 +56,13 @@ func schema_pkg_apis_advisor_v0alpha1_Check(ref common.ReferenceCallback) common
"spec": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec"),
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus"),
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus"),
},
},
},
@@ -71,291 +70,163 @@ func schema_pkg_apis_advisor_v0alpha1_Check(ref common.ReferenceCallback) common
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec", "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_investigation_v1alpha1_InvestigationAbsoluteTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Description: "AbsoluteTimeRange is a time range specified by absolute timestamps.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
"from": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Default: 0,
Type: []string{"number"},
Format: "float",
},
},
"to": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"number"},
Format: "float",
},
},
},
Required: []string{"from", "to"},
},
},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationComment(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Comment is a comment on an investigation item.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"authorUserID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"bodyMarkdown": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"authorUserID", "bodyMarkdown"},
},
},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryLogs(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DataQueryLogs is a data query for logs.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"datasource": {
SchemaProps: spec.SchemaProps{
Description: "DatasourceRef is a reference to a datasource.",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"),
},
},
"expr": {
SchemaProps: spec.SchemaProps{
Description: "expr is the expression of the query.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"maxLines": {
SchemaProps: spec.SchemaProps{
Description: "maxLines (optional) is used to limit the number of log rows returned.",
Type: []string{"integer"},
Format: "int64",
},
},
"refId": {
SchemaProps: spec.SchemaProps{
Description: "refId is the reference ID of the query.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"datasource", "expr", "refId"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryMetrics(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DataQueryMetrics is a data query for metrics.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"datasource": {
SchemaProps: spec.SchemaProps{
Description: "DatasourceRef is a reference to a datasource.",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"),
},
},
"expr": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"refId": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"datasource", "expr", "refId"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationDatasourceRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "DatasourceRef is a reference to a datasource.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check"),
},
},
},
},
},
},
Required: []string{"metadata", "items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"severity": {
SchemaProps: spec.SchemaProps{
Description: "Severity of the failure",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"reason": {
SchemaProps: spec.SchemaProps{
Description: "Human readable reason for the failure",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"action": {
SchemaProps: spec.SchemaProps{
Description: "Action to take to resolve the failure",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"stepID": {
SchemaProps: spec.SchemaProps{
Description: "Step ID that the failure is associated with",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"itemID": {
SchemaProps: spec.SchemaProps{
Description: "Item ID that the failure is associated with",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"severity", "reason", "action", "stepID", "itemID"},
},
},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"data": {
SchemaProps: spec.SchemaProps{
Description: "Generic data input that a check can receive",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
},
},
},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"report": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport"),
},
},
"operatorStates": {
SchemaProps: spec.SchemaProps{
Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState"),
},
},
},
},
},
"additionalFields": {
SchemaProps: spec.SchemaProps{
Description: "additionalFields is reserved for future use",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
},
},
},
},
Required: []string{"report"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckType(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus"),
},
},
},
Required: []string{"metadata", "spec", "status"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckTypeList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType"),
},
},
},
},
},
},
Required: []string{"metadata", "items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckTypeSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Default: "",
@@ -363,49 +234,274 @@ func schema_pkg_apis_advisor_v0alpha1_CheckTypeSpec(ref common.ReferenceCallback
Format: "",
},
},
"steps": {
"type": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"uid": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"apiVersion", "name", "type", "uid"},
},
},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationInvestigationItem(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "InvestigationItem is an item in an investigation.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"dataQuery": {
SchemaProps: spec.SchemaProps{
Description: "dataQuery contains the query used to generate this item.",
Type: []string{"object"},
Format: "",
},
},
"iconPath": {
SchemaProps: spec.SchemaProps{
Description: "iconPath (optional) is the path to the icon for the item.",
Type: []string{"string"},
Format: "",
},
},
"id": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"note": {
SchemaProps: spec.SchemaProps{
Description: "note (optional) is a comment on the item.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment"),
},
},
},
},
},
"origin": {
SchemaProps: spec.SchemaProps{
Description: "origin is where the item was created from.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"queryType": {
SchemaProps: spec.SchemaProps{
Description: "queryType is the type of the query used to generate this item.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"timeRange": {
SchemaProps: spec.SchemaProps{
Description: "AbsoluteTimeRange is a time range specified by absolute timestamps.",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange"),
},
},
"title": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"type": {
SchemaProps: spec.SchemaProps{
Description: "type is the type of the item \"timeseries\", \"heatmap\", \"log-table\" (not an enum to allow for future extensions).",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"url": {
SchemaProps: spec.SchemaProps{
Description: "url is the URL to the item.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"dataQuery", "id", "origin", "queryType", "timeRange", "title", "type", "url"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange", "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment"},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep"),
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation"),
},
},
},
},
},
},
Required: []string{"name", "steps"},
Required: []string{"metadata", "items"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep"},
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_investigation_v1alpha1_InvestigationOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Description: "InvestigationOperatorState defines model for InvestigationOperatorState.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"operatorStates": {
"descriptiveState": {
SchemaProps: spec.SchemaProps{
Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
Type: []string{"string"},
Format: "",
},
},
"details": {
SchemaProps: spec.SchemaProps{
Description: "details contains any extra information that is operator-specific",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState"),
Type: []string{"object"},
Format: "",
},
},
},
},
},
"lastEvaluation": {
SchemaProps: spec.SchemaProps{
Description: "lastEvaluation is the ResourceVersion last evaluated",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"state": {
SchemaProps: spec.SchemaProps{
Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"lastEvaluation", "state"},
},
},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "InvestigationSpec defines model for InvestigationSpec.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem"),
},
},
},
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"title": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"items", "status", "title"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem"},
}
}
func schema_pkg_apis_investigation_v1alpha1_InvestigationStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "InvestigationStatus defines model for InvestigationStatus.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"additionalFields": {
SchemaProps: spec.SchemaProps{
Description: "additionalFields is reserved for future use",
@@ -421,158 +517,36 @@ func schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref common.ReferenceCallba
},
},
},
},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckTypeStep(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"title": {
"operatorStates": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"stepID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"title", "description", "stepID"},
},
},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"lastEvaluation": {
SchemaProps: spec.SchemaProps{
Description: "lastEvaluation is the ResourceVersion last evaluated",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"state": {
SchemaProps: spec.SchemaProps{
Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"descriptiveState": {
SchemaProps: spec.SchemaProps{
Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
Type: []string{"string"},
Format: "",
},
},
"details": {
SchemaProps: spec.SchemaProps{
Description: "details contains any extra information that is operator-specific",
Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
},
},
},
},
Required: []string{"lastEvaluation", "state"},
},
},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"count": {
SchemaProps: spec.SchemaProps{
Description: "Number of elements analyzed",
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"failures": {
SchemaProps: spec.SchemaProps{
Description: "List of failures",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"),
Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState"),
},
},
},
},
},
},
Required: []string{"count", "failures"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"},
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_investigation_v1alpha1_InvestigationstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Description: "InvestigationstatusOperatorState defines model for Investigationstatus.#OperatorState.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"lastEvaluation": {
SchemaProps: spec.SchemaProps{
Description: "lastEvaluation is the ResourceVersion last evaluated",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"state": {
SchemaProps: spec.SchemaProps{
Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"descriptiveState": {
SchemaProps: spec.SchemaProps{
Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
@@ -595,6 +569,22 @@ func schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref common.Refere
},
},
},
"lastEvaluation": {
SchemaProps: spec.SchemaProps{
Description: "lastEvaluation is the ResourceVersion last evaluated",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"state": {
SchemaProps: spec.SchemaProps{
Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"lastEvaluation", "state"},
},
+50
View File
@@ -0,0 +1,50 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package apis
import (
"encoding/json"
"github.com/grafana/grafana-app-sdk/app"
)
var (
rawSchemaInvestigationv1alpha1 = []byte(`{"spec":{"description":"spec is the schema of our resource. The spec should include all the user-ediable information for the kind.","properties":{"items":{"items":{"properties":{"dataQuery":{"description":"dataQuery contains the query used to generate this item.","oneOf":[{"allOf":[{"required":["refId","datasource","expr"]},{"not":{"anyOf":[{"required":["refId","datasource","expr"]}]}}]},{"allOf":[{"required":["refId","datasource","expr"]},{"not":{"anyOf":[{"required":["refId","datasource","expr"]}]}}]}],"properties":{"datasource":{"description":"datasource is the datasource of the query.","properties":{"apiVersion":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"uid":{"type":"string"}},"required":["uid","type","apiVersion","name"],"type":"object"},"expr":{"description":"expr is the expression of the query.","type":"string"},"maxLines":{"description":"maxLines (optional) is used to limit the number of log rows returned.","format":"int64","type":"integer"},"refId":{"description":"refId is the reference ID of the query.","type":"string"}},"type":"object"},"iconPath":{"description":"iconPath (optional) is the path to the icon for the item.","type":"string"},"id":{"type":"string"},"note":{"description":"note (optional) is a comment on the item.","items":{"properties":{"authorUserID":{"type":"string"},"bodyMarkdown":{"type":"string"}},"required":["authorUserID","bodyMarkdown"],"type":"object"},"type":"array"},"origin":{"description":"origin is where the item was created from.","type":"string"},"queryType":{"description":"queryType is the type of the query used to generate this item.","enum":["logs","metrics"],"type":"string"},"timeRange":{"description":"timeRange (optional) is the time range of the item.","properties":{"from":{"type":"number"},"to":{"type":"number"}},"required":["from","to"],"type":"object"},"title":{"type":"string"},"type":{"description":"type is the type of the item \"timeseries\", \"heatmap\", \"log-table\" (not an enum to allow for future extensions).","type":"string"},"url":{"description":"url is the URL to the item.","type":"string"}},"required":["id","title","type","url","origin","timeRange","queryType","dataQuery"],"type":"object"},"type":"array"},"status":{"enum":["open","closed"],"type":"string"},"title":{"type":"string"}},"required":["title","status","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}}`)
versionSchemaInvestigationv1alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaInvestigationv1alpha1, &versionSchemaInvestigationv1alpha1)
)
var appManifestData = app.ManifestData{
AppName: "investigation",
Group: "investigation.grafana.app",
Kinds: []app.ManifestKind{
{
Kind: "Investigation",
Scope: "Namespaced",
Conversion: false,
Versions: []app.ManifestKindVersion{
{
Name: "v1alpha1",
Schema: &versionSchemaInvestigationv1alpha1,
},
},
},
},
}
func jsonToMap(j string) map[string]any {
m := make(map[string]any)
json.Unmarshal([]byte(j), &j)
return m
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("investigation")
}
@@ -9,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
investigationsv0alpha1 "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1"
investigationv1alpha1 "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1"
)
func New(cfg app.Config) (app.App, error) {
@@ -24,10 +24,7 @@ func New(cfg app.Config) (app.App, error) {
},
ManagedKinds: []simple.AppManagedKind{
{
Kind: investigationsv0alpha1.InvestigationKind(),
},
{
Kind: investigationsv0alpha1.InvestigationIndexKind(),
Kind: investigationv1alpha1.InvestigationKind(),
},
},
}
@@ -47,13 +44,10 @@ func New(cfg app.Config) (app.App, error) {
func GetKinds() map[schema.GroupVersion][]resource.Kind {
gv := schema.GroupVersion{
Group: investigationsv0alpha1.InvestigationKind().Group(),
Version: investigationsv0alpha1.InvestigationKind().Version(),
Group: investigationv1alpha1.InvestigationKind().Group(),
Version: investigationv1alpha1.InvestigationKind().Version(),
}
return map[schema.GroupVersion][]resource.Kind{
gv: {
investigationsv0alpha1.InvestigationKind(),
investigationsv0alpha1.InvestigationIndexKind(),
},
gv: {investigationv1alpha1.InvestigationKind()},
}
}
-3
View File
@@ -1,3 +0,0 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
-152
View File
@@ -1,152 +0,0 @@
[
{
"id": "896312ce-65b0-4b50-ade1-e7f04fa22c66",
"title": "Thursday morning investigation",
"hasCustomName": false,
"isFavorite": false,
"collectables": [
{
"origin": "Explore Logs",
"type": "timeseries",
"queries": [
{
"refId": "LABEL_BREAKDOWN_VALUES",
"queryType": "range",
"editorMode": "code",
"supportingQueryType": "grafana-lokiexplore-app",
"legendFormat": "{{detected_level}}",
"expr": "sum(count_over_time({service_name=\"web_app_1\"} | detected_level != \"\"[$__auto])) by (detected_level)"
}
],
"timeRange": {
"to": "2025-02-13T11:31:20.536Z",
"from": "2025-02-13T11:16:20.536Z",
"raw": {
"from": "now-15m",
"to": "now"
}
},
"datasource": {
"uid": "fe9k7u07b1a0wc"
},
"url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
"id": "LABEL_BREAKDOWN_VALUES_detected_level",
"title": "detected_level",
"logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
"createdAt": "2025-02-13T11:31:23.637Z"
}
],
"createdAt": "2025-02-13T11:31:23.636Z",
"updatedAt": "2025-02-13T11:31:23.637Z",
"viewMode": {
"mode": "compact",
"showComments": true,
"showTooltips": false
}
},
{
"id": "e9cf1958-d0ed-46b7-b597-9052c7648656",
"title": "Thursday morning investigation",
"hasCustomName": false,
"isFavorite": false,
"collectables": [
{
"origin": "Explore Logs",
"type": "timeseries",
"queries": [
{
"refId": "LABEL_BREAKDOWN_VALUES",
"queryType": "range",
"editorMode": "code",
"supportingQueryType": "grafana-lokiexplore-app",
"legendFormat": "{{detected_level}}",
"expr": "sum(count_over_time({service_name=\"web_app_1\"} | detected_level != \"\"[$__auto])) by (detected_level)"
}
],
"timeRange": {
"to": "2025-02-13T11:31:20.536Z",
"from": "2025-02-13T11:16:20.536Z",
"raw": {
"from": "now-15m",
"to": "now"
}
},
"datasource": {
"uid": "fe9k7u07b1a0wc"
},
"url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
"id": "LABEL_BREAKDOWN_VALUES_detected_level",
"title": "detected_level",
"logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
"createdAt": "2025-02-13T11:31:23.638Z"
},
{
"origin": "Explore Logs",
"type": "timeseries",
"queries": [
{
"refId": "LABEL_BREAKDOWN_VALUES",
"queryType": "range",
"editorMode": "code",
"supportingQueryType": "grafana-lokiexplore-app",
"legendFormat": "{{service_name}}",
"expr": "sum(count_over_time({service_name=\"web_app_1\",service_name != \"\"} [$__auto])) by (service_name)"
}
],
"timeRange": {
"to": "2025-02-13T11:31:20.536Z",
"from": "2025-02-13T11:16:20.536Z",
"raw": {
"from": "now-15m",
"to": "now"
}
},
"datasource": {
"uid": "fe9k7u07b1a0wc"
},
"url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
"id": "LABEL_BREAKDOWN_VALUES_service_name",
"title": "service_name",
"logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
"createdAt": "2025-02-13T11:31:41.507Z"
},
{
"origin": "Explore Logs",
"type": "timeseries",
"queries": [
{
"refId": "LABEL_BREAKDOWN_VALUES",
"queryType": "range",
"editorMode": "code",
"supportingQueryType": "grafana-lokiexplore-app",
"legendFormat": "{{service}}",
"expr": "sum(count_over_time({service_name=\"web_app_1\",service != \"\"} [$__auto])) by (service)"
}
],
"timeRange": {
"to": "2025-02-13T11:31:20.536Z",
"from": "2025-02-13T11:16:20.536Z",
"raw": {
"from": "now-15m",
"to": "now"
}
},
"datasource": {
"uid": "fe9k7u07b1a0wc"
},
"url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
"id": "LABEL_BREAKDOWN_VALUES_service",
"title": "service",
"logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
"createdAt": "2025-02-13T11:31:43.698Z"
}
],
"createdAt": "2025-02-13T11:31:23.637Z",
"updatedAt": "2025-02-13T11:31:43.698Z",
"viewMode": {
"mode": "compact",
"showComments": true,
"showTooltips": false
}
}
]
-51
View File
@@ -1,51 +0,0 @@
package investigations
// Collectable represents an item collected during investigation
#Collectable: {
id: string
createdAt: string
title: string
origin: string
type: string
queries: [...#Query] // +listType=atomic
timeRange: #TimeRange
datasource: #DatasourceRef
url: string
logoPath?: string
note: string
noteUpdatedAt: string
}
#CollectableSummary: {
id: string
title: string
logoPath: string
origin: string
}
// Query represents a data query
#Query: {
refId: string
queryType: string
editorMode: string
supportingQueryType: string
legendFormat: string
expr: string
}
// TimeRange represents a time range with both absolute and relative values
#TimeRange: {
from: string
to: string
raw: {
from: string
to: string
}
}
// DatasourceRef is a reference to a datasource
#DatasourceRef: {
uid: string
}
@@ -1 +0,0 @@
module: "github.com/grafana/grafana/apps/investigations"
@@ -1,64 +0,0 @@
package investigations
// This is our Investigation definition, which contains metadata about the kind, and the kind's schema
investigation: {
kind: "Investigation"
group: "investigations.grafana.app"
apiResource: {
groupOverride: "investigations.grafana.app"
}
pluralName: "Investigations"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
frontend: true
backend: true
options: {
generateObjectMeta: true
generateClient: true
k8sLike: true
package: "github.com/grafana/grafana/apps/investigations"
}
}
schema: {
// spec is the schema of our resource
spec: {
title: string
createdByProfile: #Person
hasCustomName: bool
isFavorite: bool
overviewNote: string
overviewNoteUpdatedAt: string
collectables: [...#Collectable] // +listType=atomic
viewMode: #ViewMode
}
}
}
}
}
// Type definition for investigation summaries
#InvestigationSummary: {
title: string
createdByProfile: #Person
hasCustomName: bool
isFavorite: bool
overviewNote: string
overviewNoteUpdatedAt: string
viewMode: #ViewMode
collectableSummaries: [...#CollectableSummary] // +listType=atomic
}
// Person represents a user profile with basic information
#Person: {
uid: string // Unique identifier for the user
name: string // Display name of the user
gravatarUrl: string // URL to user's Gravatar image
}
#ViewMode: {
mode: "compact" | "full"
showComments: bool
showTooltips: bool
}
@@ -1,37 +0,0 @@
package investigations
investigationIndex: {
kind: "InvestigationIndex"
group: "investigations.grafana.app"
apiResource: {
groupOverride: "investigations.grafana.app"
}
pluralName: "InvestigationIndexes"
current: "v0alpha1"
versions: {
"v0alpha1": {
codegen: {
frontend: true
backend: true
options: {
generateObjectMeta: true
generateClient: true
k8sLike: true
package: "github.com/grafana/grafana/apps/investigations"
}
}
schema: {
spec: {
// Title of the index, e.g. 'Favorites' or 'My Investigations'
title: string
// The Person who owns this investigation index
owner: #Person
// Array of investigation summaries
investigationSummaries: [...#InvestigationSummary] // +listType=atomic
}
}
}
}
}
-10
View File
@@ -1,10 +0,0 @@
package investigations
manifest: {
appName: "investigations"
groupOverride: "investigations.grafana.app"
kinds: [
investigation,
investigationIndex,
]
}
@@ -1,18 +0,0 @@
package v0alpha1
import "k8s.io/apimachinery/pkg/runtime/schema"
const (
// Group is the API group used by all kinds in this package
Group = "investigations.grafana.app"
// Version is the API version used by all kinds in this package
Version = "v0alpha1"
)
var (
// GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
GroupVersion = schema.GroupVersion{
Group: Group,
Version: Version,
}
)
@@ -1,28 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
time "time"
)
// metadata contains embedded CommonMetadata and can be extended with custom string fields
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
// without external reference as using the CommonMetadata reference breaks thema codegen.
type InvestigationMetadata struct {
UpdateTimestamp time.Time `json:"updateTimestamp"`
CreatedBy string `json:"createdBy"`
Uid string `json:"uid"`
CreationTimestamp time.Time `json:"creationTimestamp"`
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
Finalizers []string `json:"finalizers"`
ResourceVersion string `json:"resourceVersion"`
Generation int64 `json:"generation"`
UpdatedBy string `json:"updatedBy"`
Labels map[string]string `json:"labels"`
}
// NewInvestigationMetadata creates a new InvestigationMetadata object.
func NewInvestigationMetadata() *InvestigationMetadata {
return &InvestigationMetadata{}
}
@@ -1,140 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// Person represents a user profile with basic information
// +k8s:openapi-gen=true
type InvestigationPerson struct {
// Unique identifier for the user
Uid string `json:"uid"`
// Display name of the user
Name string `json:"name"`
// URL to user's Gravatar image
GravatarUrl string `json:"gravatarUrl"`
}
// NewInvestigationPerson creates a new InvestigationPerson object.
func NewInvestigationPerson() *InvestigationPerson {
return &InvestigationPerson{}
}
// Collectable represents an item collected during investigation
// +k8s:openapi-gen=true
type InvestigationCollectable struct {
Id string `json:"id"`
CreatedAt string `json:"createdAt"`
Title string `json:"title"`
Origin string `json:"origin"`
Type string `json:"type"`
// +listType=atomic
Queries []InvestigationQuery `json:"queries"`
TimeRange InvestigationTimeRange `json:"timeRange"`
Datasource InvestigationDatasourceRef `json:"datasource"`
Url string `json:"url"`
LogoPath *string `json:"logoPath,omitempty"`
Note string `json:"note"`
NoteUpdatedAt string `json:"noteUpdatedAt"`
}
// NewInvestigationCollectable creates a new InvestigationCollectable object.
func NewInvestigationCollectable() *InvestigationCollectable {
return &InvestigationCollectable{
TimeRange: *NewInvestigationTimeRange(),
Datasource: *NewInvestigationDatasourceRef(),
}
}
// Query represents a data query
// +k8s:openapi-gen=true
type InvestigationQuery struct {
RefId string `json:"refId"`
QueryType string `json:"queryType"`
EditorMode string `json:"editorMode"`
SupportingQueryType string `json:"supportingQueryType"`
LegendFormat string `json:"legendFormat"`
Expr string `json:"expr"`
}
// NewInvestigationQuery creates a new InvestigationQuery object.
func NewInvestigationQuery() *InvestigationQuery {
return &InvestigationQuery{}
}
// TimeRange represents a time range with both absolute and relative values
// +k8s:openapi-gen=true
type InvestigationTimeRange struct {
From string `json:"from"`
To string `json:"to"`
Raw InvestigationV0alpha1TimeRangeRaw `json:"raw"`
}
// NewInvestigationTimeRange creates a new InvestigationTimeRange object.
func NewInvestigationTimeRange() *InvestigationTimeRange {
return &InvestigationTimeRange{
Raw: *NewInvestigationV0alpha1TimeRangeRaw(),
}
}
// DatasourceRef is a reference to a datasource
// +k8s:openapi-gen=true
type InvestigationDatasourceRef struct {
Uid string `json:"uid"`
}
// NewInvestigationDatasourceRef creates a new InvestigationDatasourceRef object.
func NewInvestigationDatasourceRef() *InvestigationDatasourceRef {
return &InvestigationDatasourceRef{}
}
// +k8s:openapi-gen=true
type InvestigationViewMode struct {
Mode InvestigationViewModeMode `json:"mode"`
ShowComments bool `json:"showComments"`
ShowTooltips bool `json:"showTooltips"`
}
// NewInvestigationViewMode creates a new InvestigationViewMode object.
func NewInvestigationViewMode() *InvestigationViewMode {
return &InvestigationViewMode{}
}
// spec is the schema of our resource
// +k8s:openapi-gen=true
type InvestigationSpec struct {
Title string `json:"title"`
CreatedByProfile InvestigationPerson `json:"createdByProfile"`
HasCustomName bool `json:"hasCustomName"`
IsFavorite bool `json:"isFavorite"`
OverviewNote string `json:"overviewNote"`
OverviewNoteUpdatedAt string `json:"overviewNoteUpdatedAt"`
// +listType=atomic
Collectables []InvestigationCollectable `json:"collectables"`
ViewMode InvestigationViewMode `json:"viewMode"`
}
// NewInvestigationSpec creates a new InvestigationSpec object.
func NewInvestigationSpec() *InvestigationSpec {
return &InvestigationSpec{
CreatedByProfile: *NewInvestigationPerson(),
ViewMode: *NewInvestigationViewMode(),
}
}
// +k8s:openapi-gen=true
type InvestigationV0alpha1TimeRangeRaw struct {
From string `json:"from"`
To string `json:"to"`
}
// NewInvestigationV0alpha1TimeRangeRaw creates a new InvestigationV0alpha1TimeRangeRaw object.
func NewInvestigationV0alpha1TimeRangeRaw() *InvestigationV0alpha1TimeRangeRaw {
return &InvestigationV0alpha1TimeRangeRaw{}
}
// +k8s:openapi-gen=true
type InvestigationViewModeMode string
const (
InvestigationViewModeModeCompact InvestigationViewModeMode = "compact"
InvestigationViewModeModeFull InvestigationViewModeMode = "full"
)
@@ -1,44 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type InvestigationstatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated
LastEvaluation string `json:"lastEvaluation"`
// state describes the state of the lastEvaluation.
// It is limited to three possible states for machine evaluation.
State InvestigationStatusOperatorStateState `json:"state"`
// descriptiveState is an optional more descriptive state field which has no requirements on format
DescriptiveState *string `json:"descriptiveState,omitempty"`
// details contains any extra information that is operator-specific
Details map[string]interface{} `json:"details,omitempty"`
}
// NewInvestigationstatusOperatorState creates a new InvestigationstatusOperatorState object.
func NewInvestigationstatusOperatorState() *InvestigationstatusOperatorState {
return &InvestigationstatusOperatorState{}
}
// +k8s:openapi-gen=true
type InvestigationStatus struct {
// operatorStates is a map of operator ID to operator state evaluations.
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
OperatorStates map[string]InvestigationstatusOperatorState `json:"operatorStates,omitempty"`
// additionalFields is reserved for future use
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
}
// NewInvestigationStatus creates a new InvestigationStatus object.
func NewInvestigationStatus() *InvestigationStatus {
return &InvestigationStatus{}
}
// +k8s:openapi-gen=true
type InvestigationStatusOperatorStateState string
const (
InvestigationStatusOperatorStateStateSuccess InvestigationStatusOperatorStateState = "success"
InvestigationStatusOperatorStateStateInProgress InvestigationStatusOperatorStateState = "in_progress"
InvestigationStatusOperatorStateStateFailed InvestigationStatusOperatorStateState = "failed"
)

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