Compare commits

..

119 Commits

Author SHA1 Message Date
github-actions[bot]
4b398c1311 apply security patch: release-11.5.3/341-202503050903.patch
commit e225f2b87c2e53b9c0efb516d93ee79b48e0704d
Author: oscarkilhed <oscar.kilhed@grafana.com>
Date:   Fri Feb 28 16:32:58 2025 +0100

    Limit number of characters in the title
2025-03-18 13:48:03 +00: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
3263 changed files with 67026 additions and 139242 deletions

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.',
},
],
},
],

File diff suppressed because it is too large Load Diff

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

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

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"

View File

@@ -25,7 +25,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- ./bin/build verify-drone
@@ -75,7 +75,7 @@ steps:
- go install github.com/bazelbuild/buildtools/buildifier@latest
- buildifier --lint=warn -mode=check -r .
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: lint-starlark
trigger:
event:
@@ -179,7 +179,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- yarn betterer:ci
- yarn betterer ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -339,16 +339,6 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
- commands:
- yarn generate-apis
- "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
]; then\n echo $file_diff\n echo \"\nAPI client
generation has not been committed. Please run 'yarn generate-apis', commit the
changes and push again.\"\n exit 1\n fi\n "
depends_on:
- yarn-install
image: node:22-bookworm
name: verify-api-clients
trigger:
event:
- pull_request
@@ -437,7 +427,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -446,21 +436,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -469,7 +459,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend-integration
trigger:
event:
@@ -489,7 +479,6 @@ trigger:
- public/app/plugins/**/plugin.json
- docs/sources/setup-grafana/configure-grafana/feature-toggles/**
- devenv/**
- apps/**
type: docker
volumes:
- host:
@@ -524,7 +513,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- echo $(/usr/bin/github-app-external-token) > /github-app/token
@@ -569,16 +558,16 @@ steps:
- apk add --update make
- make gen-go
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-openapi-spec
trigger:
event:
@@ -599,7 +588,6 @@ trigger:
- public/app/plugins/**/plugin.json
- devenv/**
- .bingo/**
- apps/**
type: docker
volumes:
- host:
@@ -655,7 +643,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -665,7 +653,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -674,7 +662,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- yarn install --immutable || yarn install --immutable
@@ -712,7 +700,7 @@ steps:
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.24.1 --yarn-cache=$$YARN_CACHE_FOLDER
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
@@ -1110,7 +1098,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
@@ -1124,7 +1112,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1133,14 +1121,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -1161,7 +1149,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -1182,7 +1170,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -1198,7 +1186,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -1214,7 +1202,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -1230,7 +1218,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: remote-alertmanager-integration-tests
trigger:
event:
@@ -1312,7 +1300,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
trigger:
event:
@@ -1433,7 +1421,7 @@ steps:
&& return 1; fi
depends_on:
- clone-enterprise
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: swagger-gen
trigger:
event:
@@ -1538,7 +1526,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1549,7 +1537,7 @@ steps:
- CODEGEN_VERIFY=1 make gen-cue
depends_on:
- clone-enterprise
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1559,14 +1547,14 @@ steps:
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on:
- clone-enterprise
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- apk add --update build-base
@@ -1574,7 +1562,7 @@ steps:
- go test -v -run=^$ -benchmem -timeout=1h -count=8 -bench=. ${GO_PACKAGES}
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: sqlite-benchmark-integration-tests
- commands:
- apk add --update build-base
@@ -1586,7 +1574,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: postgres-benchmark-integration-tests
- commands:
- apk add --update build-base
@@ -1597,7 +1585,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: mysql-8.0-benchmark-integration-tests
trigger:
event:
@@ -1669,7 +1657,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
trigger:
branch: main
@@ -1717,7 +1705,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- yarn betterer:ci
- yarn betterer ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -1796,16 +1784,6 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
- commands:
- yarn generate-apis
- "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
]; then\n echo $file_diff\n echo \"\nAPI client
generation has not been committed. Please run 'yarn generate-apis', commit the
changes and push again.\"\n exit 1\n fi\n "
depends_on:
- yarn-install
image: node:22-bookworm
name: verify-api-clients
trigger:
branch: main
event:
@@ -1852,7 +1830,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1861,21 +1839,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -1884,7 +1862,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend-integration
trigger:
branch: main
@@ -1929,22 +1907,22 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- apk add --update make
- make gen-go
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-openapi-spec
- commands:
- ./bin/build verify-drone
@@ -2076,7 +2054,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -2086,7 +2064,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -2095,7 +2073,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2106,7 +2084,8 @@ steps:
- apk add --update jq
- new_version=$(cat package.json | jq -r .version | sed s/pre/${DRONE_BUILD_NUMBER}/g)
- 'echo "New version: $new_version"'
- yarn nx release version $new_version --group grafanaPackages,privatePackages,plugins
- yarn run lerna version $new_version --exact --no-git-tag-version --no-push --force-publish
-y
- yarn install --mode=update-lockfile
depends_on:
- yarn-install
@@ -2131,7 +2110,7 @@ steps:
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.24.1 --yarn-cache=$$YARN_CACHE_FOLDER
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
@@ -2606,7 +2585,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
@@ -2620,7 +2599,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -2629,14 +2608,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -2657,7 +2636,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -2678,7 +2657,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -2694,7 +2673,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -2710,7 +2689,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -2726,7 +2705,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: remote-alertmanager-integration-tests
trigger:
branch: main
@@ -2864,7 +2843,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- yarn betterer:ci
- yarn betterer ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -2941,16 +2920,6 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
- commands:
- yarn generate-apis
- "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
]; then\n echo $file_diff\n echo \"\nAPI client
generation has not been committed. Please run 'yarn generate-apis', commit the
changes and push again.\"\n exit 1\n fi\n "
depends_on:
- yarn-install
image: node:22-bookworm
name: verify-api-clients
trigger:
branch:
- instant
@@ -2995,7 +2964,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -3004,21 +2973,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -3027,7 +2996,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend-integration
trigger:
branch:
@@ -3070,22 +3039,22 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- apk add --update make
- make gen-go
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: validate-openapi-spec
trigger:
branch:
@@ -3164,7 +3133,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
@@ -3178,7 +3147,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -3187,14 +3156,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -3215,7 +3184,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -3236,7 +3205,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -3252,7 +3221,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -3268,7 +3237,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -3284,7 +3253,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: remote-alertmanager-integration-tests
trigger:
branch:
@@ -3384,7 +3353,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts docker fetch --edition oss
@@ -3516,7 +3485,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts docker fetch --edition oss
@@ -3657,7 +3626,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts packages --artifacts-editions=oss --tag $${DRONE_TAG} --src-bucket
@@ -3749,7 +3718,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- yarn install --immutable || yarn install --immutable
@@ -3849,7 +3818,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- depends_on:
- compile-build-cmd
@@ -3946,7 +3915,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: compile-build-cmd
- commands:
- ./bin/build publish grafana-com --edition oss ${DRONE_TAG}
@@ -4008,7 +3977,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4083,7 +4052,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4200,7 +4169,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4296,7 +4265,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- yarn betterer:ci
- yarn betterer ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -4351,7 +4320,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -4360,21 +4329,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -4383,7 +4352,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: test-backend-integration
trigger:
cron:
@@ -4437,7 +4406,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4581,7 +4550,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4686,9 +4655,9 @@ steps:
path: /github-app
- commands:
- export GITHUB_TOKEN=$(cat /github-app/token)
- dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
--enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION}
--go-version=1.23.5
- 'dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
--enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION} '
- --go-version=1.24.1
depends_on:
- github-app-generate-token
environment:
@@ -4709,7 +4678,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
GO_VERSION: 1.23.5
GO_VERSION: 1.24.1
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4733,8 +4702,6 @@ steps:
- printenv GCP_KEY_BASE64 | base64 -d > /tmp/key.json
- gcloud auth activate-service-account --key-file=/tmp/key.json
- gcloud storage cp -r dist/* $${UPLOAD_TO}
depends_on:
- rgm-build
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
@@ -4775,8 +4742,6 @@ volumes:
name: docker
- name: github-app
path: /github-app
- name: github-app
temp: {}
---
clone:
retries: 3
@@ -4847,7 +4812,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -4856,14 +4821,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -4884,7 +4849,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -4905,7 +4870,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -4921,7 +4886,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -4937,7 +4902,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -4953,7 +4918,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
image: golang:1.23.5-alpine
image: golang:1.24.1-alpine
name: remote-alertmanager-integration-tests
trigger:
event:
@@ -5256,7 +5221,7 @@ steps:
- commands:
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM docker:27-cli
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine/git:2.40.1
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.23.5-alpine
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.24.1-alpine
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22.11.0-alpine
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22-bookworm
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM google/cloud-sdk:431.0.0
@@ -5294,7 +5259,7 @@ steps:
- commands:
- trivy --exit-code 1 --severity HIGH,CRITICAL docker:27-cli
- trivy --exit-code 1 --severity HIGH,CRITICAL alpine/git:2.40.1
- trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.23.5-alpine
- trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.24.1-alpine
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22.11.0-alpine
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22-bookworm
- trivy --exit-code 1 --severity HIGH,CRITICAL google/cloud-sdk:431.0.0
@@ -5563,6 +5528,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
hmac: 950ed494abe239bcbd1771dcd1a49e365a2b5fba7f8e8613e015e14b21c13341
hmac: b2d4333ae94bbab37ed239db0a61ce3667ba7da84be024584aba367602e064f6
...

58
.github/CODEOWNERS vendored
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,12 +436,12 @@
/.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
/.yarnrc.yml @grafana/frontend-ops
/yarn.lock @grafana/frontend-ops
/lerna.json @grafana/frontend-ops
/.prettierrc.js @grafana/frontend-ops
/.vim @zoltanbedi
/jest.config.js @grafana/frontend-ops
@@ -464,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
@@ -501,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
@@ -515,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
@@ -543,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
@@ -592,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
@@ -605,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
@@ -629,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
@@ -643,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
@@ -733,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
@@ -753,13 +746,8 @@ embed.go @grafana/grafana-as-code
/.github/pr-checks.json @tolzhabayev
/.github/pr-commands.json @tolzhabayev
/.github/renovate.json5 @grafana/frontend-ops
/.github/actions/report-coverage @grafana/grafana-backend-group
/.github/actions/run-backend-tests @grafana/grafana-backend-group
/.github/actions/setup-enterprise @grafana/grafana-backend-group
/.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/alerting-update-module.yml @grafana/alerting-backend
/.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/backport.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/bump-version.yml @grafana/grafana-developer-enablement-squad
@@ -773,11 +761,9 @@ 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
/.github/workflows/feature-toggles-ci.yml @grafana/docs-tooling
/.github/workflows/github-release.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/issue-opened.yml @grafana/grafana-community-support
/.github/workflows/metrics-collector.yml @torkelo
@@ -788,21 +774,20 @@ embed.go @grafana/grafana-as-code
/.github/workflows/pr-codeql-analysis-python.yml @DanCech
/.github/workflows/pr-commands.yml @tolzhabayev
/.github/workflows/pr-patch-check.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/pr-test-backend.yml @grafana/grafana-backend-group
/.github/workflows/sync-mirror.yml @grafana/grafana-developer-enablement-squad
/.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
@@ -815,7 +800,6 @@ embed.go @grafana/grafana-as-code
/.github/workflows/trivy-scan.yml @grafana/grafana-backend-services-squad
/.github/workflows/changelog.yml @zserge
/.github/workflows/actions/changelog @zserge
/.github/workflows/frontend-unit-tests.yml @grafana/grafana-frontend-platform
# Generated files not requiring owner approval
/packages/grafana-data/src/types/featureToggles.gen.ts @grafanabot

View File

@@ -1,46 +0,0 @@
name: 'Report Coverage'
description: 'Processes and uploads coverage reports from Go tests'
inputs:
unit-cov-path:
description: 'Path to unit test coverage file'
required: true
integration-cov-path:
description: 'Path to integration test coverage file'
required: true
runs:
using: "composite"
steps:
- name: Join coverage outputs
shell: bash
run: |
cp ${{ inputs.unit-cov-path }} backend.cov
tail -n+2 ${{ inputs.integration-cov-path }} >> backend.cov
- name: Convert coverage info to per-func stats
shell: bash
run: go tool cover -func backend.cov > backend-funcs.log
- name: Convert coverage info to HTML
shell: bash
run: go tool cover -html backend.cov -o backend.html
- name: Upload coverage file
uses: actions/upload-artifact@v4
with:
name: backend-cov
path: |
backend.cov
backend-funcs.log
backend.html
retention-days: 30
compression-level: 9
- name: Set summary to total coverage
shell: bash
run: |
echo '# Coverage' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
grep 'total:' backend-funcs.log | tr '\t' ' ' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

View File

@@ -1,24 +0,0 @@
name: 'Run Backend Tests'
description: 'Runs Grafana backend test suites'
inputs:
coverage-opts:
description: 'Coverage options to pass to the test command (empty for no coverage)'
required: false
default: ''
test-command:
description: 'The test command to run'
required: false
default: 'make gen-go test-go-unit'
runs:
using: "composite"
steps:
- name: Run tests
shell: bash
run: |
if [ -n "${{ inputs.coverage-opts }}" ]; then
COVER_OPTS="${{ inputs.coverage-opts }}" ${{ inputs.test-command }}
else
${{ inputs.test-command }}
fi

View File

@@ -1,48 +0,0 @@
name: 'Setup Grafana Enterprise'
description: 'Clones and sets up Grafana Enterprise repository for testing'
inputs:
github-app-name:
description: 'Name of the GitHub App in Vault'
required: false
default: 'grafana-ci-bot'
runs:
using: "composite"
steps:
- name: Retrieve GitHub App secrets
id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1
with:
repo_secrets: |
APP_ID=${{ inputs.github-app-name }}:app-id
APP_INSTALLATION_ID=${{ inputs.github-app-name }}:app-installation-id
PRIVATE_KEY=${{ inputs.github-app-name }}:private-key
- name: Generate GitHub App token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ env.APP_ID }}
private-key: ${{ env.PRIVATE_KEY }}
repositories: "grafana-enterprise"
owner: "grafana"
- name: Setup Enterprise
shell: bash
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
git clone https://x-access-token:${GH_TOKEN}@github.com/grafana/grafana-enterprise.git ../grafana-enterprise;
cd ../grafana-enterprise
if git checkout ${GITHUB_HEAD_REF}; then
echo "checked out ${GITHUB_HEAD_REF}"
elif git checkout ${GITHUB_BASE_REF}; then
echo "checked out ${GITHUB_BASE_REF}"
else
git checkout main
fi
./build.sh

View File

@@ -640,7 +640,7 @@
"name": "area/configuration",
"action": "addToProject",
"addToProject": {
"url": "https://github.com/orgs/grafana/projects/665"
"url": "https://github.com/orgs/grafana/projects/96"
}
},
{
@@ -744,7 +744,7 @@
"name": "area/backend/db/postgres",
"action": "addToProject",
"addToProject": {
"url": "https://github.com/orgs/grafana/projects/835"
"url": "https://github.com/orgs/grafana/projects/96"
}
},
{

View File

@@ -8,7 +8,7 @@ updates:
directories:
- "/"
- "/apps/playlist"
- "/apps/investigations"
- "/apps/investigation"
- "/pkg/aggregator"
- "/pkg/apimachinery"
- "/pkg/apiserver"

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",
@@ -21,7 +22,7 @@
"scripts/webpack/**/*",
"package.json",
"tsconfig.json",
"nx.json",
"lerna.json",
".prettierrc.js",
".eslintrc",
"**/*.mdx"
@@ -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"
}
]
]

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: [
@@ -32,7 +33,6 @@
extends: ["schedule:monthly"],
groupName: "Storybook updates",
matchPackageNames: ["/^@?storybook/"],
rangeStrategy: "bump",
},
{
groupName: "React Aria",

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}`);

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.

View File

@@ -1,136 +0,0 @@
name: Update Alerting Module
on:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update-grafana:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
- name: Check if update branch exists
run: |
if git ls-remote --heads origin update-alerting-module | grep -q 'update-alerting-module'; then
echo "Branch 'update-alerting-module' already exists. There might be an open PR with Grafana updates."
echo "Please review and merge/close the existing PR before running this workflow again."
exit 1
fi
- name: Setup Go
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # 5.3.0
with:
"go-version-file": "go.mod"
- name: Extract current commit hash of alerting module
id: current-commit
run: |
FROM_COMMIT=$(go list -m -json github.com/grafana/alerting | jq -r '.Version' | grep -oP '(?<=-)[a-f0-9]+$')
echo "from_commit=$FROM_COMMIT" >> $GITHUB_OUTPUT
- name: Get current branch name
id: current-branch-name
run: echo "name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> "$GITHUB_OUTPUT"
- name: Get latest commit
id: latest-commit
env:
GH_TOKEN: ${{ github.token }}
run: |
BRANCH="${{ steps.current-branch-name.outputs.name }}"
TO_COMMIT=$(gh api repos/grafana/alerting/commits/$BRANCH --jq '.sha')
if [ -z "$TO_COMMIT" ]; then
echo "Branch $BRANCH not found in alerting repo, falling back to main branch"
exit 1
fi
echo "to_commit=$TO_COMMIT" >> $GITHUB_OUTPUT
- name: Compare commit hashes
run: |
FROM_COMMIT="${{ steps.current-commit.outputs.from_commit }}"
TO_COMMIT="${{ steps.latest-commit.outputs.to_commit }}"
# Compare just the length of the shorter hash
SHORT_TO_COMMIT="${TO_COMMIT:0:${#FROM_COMMIT}}"
if [ "$FROM_COMMIT" = "$SHORT_TO_COMMIT" ]; then
echo "Current version ($FROM_COMMIT) is already at latest ($SHORT_TO_COMMIT). No update needed."
exit 0
fi
echo "Updates available: $FROM_COMMIT -> $TO_COMMIT"
- name: Check for commit history
id: check-commits
env:
GH_TOKEN: ${{ github.token }}
run: |
# get all commits that contains 'Alerting:' in the message
ALERTING_COMMITS=$(gh api repos/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }} \
--jq '.commits[].commit.message | split("\n")[0]') || true
# Use printf instead of echo -e for better multiline handling
printf "%s\n" "$ALERTING_COMMITS"
# make the list for markdown and replace PR numbers with links
ALERTING_COMMITS_FORMATTED=$(echo "$ALERTING_COMMITS" | while read -r line; do echo "- $line" | sed -E 's/\(#([0-9]+)\)/[#\1](https:\/\/github.com\/grafana\/grafana\/pull\/\1)/g'; done)
echo "alerting_commits<<EOF" >> $GITHUB_OUTPUT
echo "$ALERTING_COMMITS_FORMATTED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Update alerting module
env:
GOSUMDB: off
run: |
go get github.com/grafana/alerting@${{ steps.latest-commit.outputs.to_commit }}
make update-workspace
- id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # 1.1.0
with:
repo_secrets: |
GITHUB_APP_ID=alerting-team:app-id
GITHUB_APP_PRIVATE_KEY=alerting-team:private-key
- name: "Generate token"
id: generate_token
uses: actions/create-github-app-token@0d564482f06ca65fa9e77e2510873638c82206f2 # 1.11.5
with:
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # 7.0.6
id: create-pr
with:
token: '${{ steps.generate_token.outputs.token }}'
title: 'Alerting: Update alerting module to ${{ steps.latest-commit.outputs.to_commit }}'
branch: alerting/update-alerting-module
delete-branch: true
body: |
Updates Grafana Alerting module to latest version.
Compare changes: https://github.com/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }}
<details>
<summary>Commits</summary>
${{ steps.check-commits.outputs.alerting_commits }}
</details>
Created by: [GitHub Action Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: Add PR URL to Summary
if: steps.create-pr.outputs.pull-request-url != ''
run: |
echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY

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

View File

@@ -52,7 +52,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -67,4 +67,4 @@ jobs:
make build-go
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v2

View File

@@ -11,21 +11,14 @@ on:
jobs:
deploy-pr-preview:
if: "!github.event.pull_request.head.repo.fork"
if: ${{ ! github.event.pull_request.head.repo.fork }}
uses: grafana/writers-toolkit/.github/workflows/deploy-preview.yml@main
with:
sha: ${{ github.event.pull_request.head.sha }}
branch: ${{ github.head_ref }}
event_number: ${{ github.event.number }}
repo: grafana
sha: ${{ github.event.pull_request.head.sha }}
sources: |
[
{
"index_file": "content/docs/grafana/_index.md",
"relative_prefix": "/docs/grafana/latest/",
"repo": "grafana",
"source_directory": "docs/sources",
"website_directory": "content/docs/grafana/latest"
}
]
title: ${{ github.event.pull_request.title }}
repo: grafana
website_directory: content/docs/grafana/latest
relative_prefix: /docs/grafana/latest/
index_file: true

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 }}

View File

@@ -1,25 +0,0 @@
name: Feature toggles CI
on:
pull_request:
paths:
- 'pkg/services/featuremgmt/toggles_gen_test.go'
- 'pkg/services/featuremgmt/registry.go'
- 'docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: Run feature toggle tests
run: go test -v -run TestFeatureToggleFiles ./pkg/services/featuremgmt/

View File

@@ -1,29 +0,0 @@
name: Frontend tests
on:
pull_request:
push:
branches:
- main
- release-*.*.*
jobs:
test-frontend:
runs-on: ubuntu-latest-8-cores
name: "Unit tests (${{ matrix.chunk }} / 8)"
strategy:
fail-fast: true
matrix:
chunk: [1, 2, 3, 4, 5, 6, 7, 8]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
cache-dependency-path: 'yarn.lock'
- run: yarn install --immutable --check-cache
- run: yarn run test:ci
env:
TEST_MAX_WORKERS: 2
TEST_SHARD: ${{ matrix.chunk }}
TEST_SHARD_TOTAL: 8

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 }}

View File

@@ -1,106 +0,0 @@
name: Test Backend
on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
- 'docs/**'
- '**/*.md'
pull_request:
paths-ignore:
- 'docs/**'
- '**/*.md'
permissions:
contents: read
id-token: write
env:
EDITION: 'oss'
jobs:
test-backend:
name: Test Backend
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.23.5'
cache: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential shared-mime-info make
- name: Get runner name
run: echo ${{ runner.name }}
- name: Setup Enterprise (PR only)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
uses: ./.github/actions/setup-enterprise
- name: Verify CUE generation
run: CODEGEN_VERIFY=1 make gen-cue
- name: Verify Jsonnet generation
run: CODEGEN_VERIFY=1 make gen-jsonnet
- name: Check if coverage should be generated
id: check-coverage
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "PR changed files:"
files=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --jq '.[].filename')
echo "$files"
if echo "$files" | grep -E "(pkg/|go\.)"; then
echo "Coverage will be generated: true (PR changes)"
echo "generate=true" >> $GITHUB_OUTPUT
else
echo "Coverage will be generated: false"
echo "generate=false" >> $GITHUB_OUTPUT
fi
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]] && \
[[ "${{ github.event.head_commit.modified }}" =~ (pkg/|go\.|\.github/workflows/pr-test-backend\.yml) ]]; then
echo "Coverage will be generated: true (push to main)"
echo "generate=true" >> $GITHUB_OUTPUT
else
echo "Coverage will be generated: false"
echo "generate=false" >> $GITHUB_OUTPUT
fi
- name: Run backend tests
uses: ./.github/actions/run-backend-tests
with:
coverage-opts: ${{ steps.check-coverage.outputs.generate == 'true' && '-coverprofile=unit.cov -coverpkg=github.com/grafana/grafana/...' || '' }}
test-command: 'make gen-go test-go-unit'
- name: Run backend integration tests
uses: ./.github/actions/run-backend-tests
with:
coverage-opts: ${{ steps.check-coverage.outputs.generate == 'true' && '-coverprofile=integration.cov -coverpkg=github.com/grafana/grafana/...' || '' }}
test-command: 'make gen-go test-go-integration'
- name: Generate Coverage Report
if: steps.check-coverage.outputs.generate == 'true'
uses: ./.github/actions/report-coverage
with:
unit-cov-path: unit.cov
integration-cov-path: integration.cov
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

View File

@@ -74,7 +74,6 @@ jobs:
ref: ${{ steps.branch.outputs.branch }}
fetch-depth: 0
fetch-tags: true
token: ${{ steps.generate_token.outputs.token }}
- name: Checkout Grafana (main)
uses: actions/checkout@v4
with:
@@ -82,7 +81,6 @@ jobs:
fetch-depth: '0'
fetch-tags: 'false'
path: .grafana-main
token: ${{ steps.generate_token.outputs.token }}
- name: Setup nodejs environment
uses: actions/setup-node@v4
with:
@@ -145,8 +143,7 @@ jobs:
- name: Add package.json changes
run: |
git add package.json yarn.lock packages public
test -e e2e/test-plugins && git add e2e/test-plugins
git add package.json lerna.json yarn.lock packages public
git commit -m "Update version to ${{ inputs.version }}"
- name: Git push

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
.github/workflows/sbom-report.yml vendored Normal file
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

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 \

19
.gitignore vendored
View File

@@ -16,7 +16,6 @@ vendor/
/requests
tsconfig.tsbuildinfo
__debug_bin*
*.cov
# yarn
.yarn/cache
@@ -41,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
@@ -105,19 +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
!/pkg/extensions/enterprise_imports.go
/public/app/extensions
!/public/app/extensions/.keep
debug.test
/examples/*/dist
/packaging/**/*.rpm
@@ -177,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

View File

@@ -1,5 +1,5 @@
run:
timeout: 15m
timeout: 10m
concurrency: 10
allow-parallel-runners: true
linters-settings:
@@ -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
.ignore
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

View File

@@ -33,6 +33,3 @@ public/mockServiceWorker.js
# Crowdin files
public/locales/**/*.json
/.nx/cache
/.nx/workspace-data

View File

@@ -1,5 +0,0 @@
MinAlertLevel = warning
[*]
BasedOnStyles = Grafana
TokenIgnores = (<http[^\n]+>+?), \*\*[^\n]+\*\*

28
.vscode/launch.json vendored
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",

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

View File

@@ -23,92 +23,6 @@
- **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.4.2 START -->
# 11.4.2 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99924](https://github.com/grafana/grafana/pull/99924), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Auth:** Fix redirect with JWT auth URL login [#100494](https://github.com/grafana/grafana/pull/100494), [@mgyongyosi](https://github.com/mgyongyosi)
- **AuthN:** Refetch user on "ErrUserAlreadyExists" [#100585](https://github.com/grafana/grafana/pull/100585), [@kalleep](https://github.com/kalleep)
- **Azure:** Correctly set application insights resource values [#99598](https://github.com/grafana/grafana/pull/99598), [@aangelisc](https://github.com/aangelisc)
- **Dashboards:** Bring back scripted dashboards [#100629](https://github.com/grafana/grafana/pull/100629), [@dprokop](https://github.com/dprokop)
- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100077](https://github.com/grafana/grafana/pull/100077), [@clord](https://github.com/clord)
- **RBAC:** Don't check folder access if `annotationPermissionUpdate` FT is enabled [#100116](https://github.com/grafana/grafana/pull/100116), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
<!-- 11.4.2 END -->
<!-- 11.3.4 START -->
# 11.3.4 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99923](https://github.com/grafana/grafana/pull/99923), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Auth:** Fix redirect with JWT auth URL login [#100495](https://github.com/grafana/grafana/pull/100495), [@mgyongyosi](https://github.com/mgyongyosi)
- **Azure:** Correctly set application insights resource values [#99597](https://github.com/grafana/grafana/pull/99597), [@aangelisc](https://github.com/aangelisc)
- **Dashboards:** Bring back scripted dashboards [#100627](https://github.com/grafana/grafana/pull/100627), [@dprokop](https://github.com/dprokop)
- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100076](https://github.com/grafana/grafana/pull/100076), [@clord](https://github.com/clord)
<!-- 11.3.4 END -->
<!-- 11.2.7 START -->
# 11.2.7 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99922](https://github.com/grafana/grafana/pull/99922), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Azure:** Correctly set application insights resource values [#99596](https://github.com/grafana/grafana/pull/99596), [@aangelisc](https://github.com/aangelisc)
<!-- 11.2.7 END -->
<!-- 11.1.12 START -->
# 11.1.12 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99917](https://github.com/grafana/grafana/pull/99917), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Azure:** Correctly set application insights resource values [#99595](https://github.com/grafana/grafana/pull/99595), [@aangelisc](https://github.com/aangelisc)
<!-- 11.1.12 END -->
<!-- 11.0.11 START -->
# 11.0.11 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#100730](https://github.com/grafana/grafana/pull/100730), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Azure:** Correctly set application insights resource values [#99594](https://github.com/grafana/grafana/pull/99594), [@aangelisc](https://github.com/aangelisc)
<!-- 11.0.11 END -->
<!-- 10.4.16 START -->
# 10.4.16 (2025-02-18)
### Features and enhancements
- **Docker:** Use our own glibc 2.40 binaries [#99920](https://github.com/grafana/grafana/pull/99920), [@DanCech](https://github.com/DanCech)
### Bug fixes
- **Dashboard:** Fix for overwriting an edited dashboard in the old architecture [#100288](https://github.com/grafana/grafana/pull/100288), [@bfmatei](https://github.com/bfmatei)
<!-- 10.4.16 END -->
<!-- 11.5.1 START -->
# 11.5.1 (2025-02-03)
@@ -287,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)

View File

@@ -6,7 +6,7 @@
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 \
@@ -124,7 +124,6 @@ FROM ${JS_SRC} AS js-src
FROM ${BASE_IMAGE}
LABEL maintainer="Grafana Labs <hello@grafana.com>"
LABEL org.opencontainers.image.source="https://github.com/grafana/grafana"
ARG GF_UID="472"
ARG GF_GID="0"

View File

@@ -8,4 +8,4 @@
- @davkal
- Docs:
- @chri2547
- @JohnnyK-Grafana
- @brendamuir

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 ?=
@@ -248,7 +249,8 @@ test-go: test-go-unit test-go-integration
.PHONY: test-go-unit
test-go-unit: ## Run unit tests for backend with flags.
@echo "test backend unit tests"
$(GO) test $(GO_RACE_FLAG) -short -covermode=atomic -coverprofile=unit.cov -timeout=30m $(GO_TEST_FILES)
printf '$(GO_TEST_FILES)' | xargs \
$(GO) test $(GO_RACE_FLAG) -short -covermode=atomic -timeout=30m
.PHONY: test-go-unit-pretty
test-go-unit-pretty: check-tparse
@@ -261,7 +263,7 @@ test-go-unit-pretty: check-tparse
.PHONY: test-go-integration
test-go-integration: ## Run integration tests for backend with flags.
@echo "test backend integration tests"
$(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegration" -covermode=atomic -coverprofile=integration.cov -timeout=5m $(GO_INTEGRATION_TESTS)
$(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegration" -covermode=atomic -timeout=5m $(GO_INTEGRATION_TESTS)
.PHONY: test-go-integration-alertmanager
test-go-integration-alertmanager: ## Run integration tests for the remote alertmanager (config taken from the mimir_backend block).
@@ -270,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"
@@ -428,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.

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

View File

@@ -1 +0,0 @@
plugin/src

View File

@@ -1,3 +0,0 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none

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
)

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=

View File

@@ -1,53 +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
}
#ErrorLink: {
// URL to a page with more information about the error
url: string
// Human readable error message
message: string
}
#ReportFailure: {
// Severity of the failure
severity: "high" | "low"
// Step ID that the failure is associated with
stepID: string
// Human readable identifier of the item that failed
item: string
// Links to actions that can be taken to resolve the failure
links: [...#ErrorLink]
}
#Report: {
// Number of elements analyzed
count: int
// List of failures
failures: [...#ReportFailure]
}
spec: #Data
status: {
report: #Report
}
}
}
}
}

View File

@@ -1,27 +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
resolution: string
}
spec: {
name: string
steps: [...#Step]
}
}
}
}
}

View File

@@ -1,4 +0,0 @@
module: "github.com/grafana/grafana/apps/advisor/kinds"
language: {
version: "v0.9.0"
}

View File

@@ -1,10 +0,0 @@
package advisor
manifest: {
appName: "advisor"
groupOverride: "advisor.grafana.app"
kinds: [
check,
checktype,
]
}

View File

@@ -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{}

View File

@@ -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{}
}

View File

@@ -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{}

View File

@@ -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

View File

@@ -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{}
}

View File

@@ -1,98 +0,0 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type CheckErrorLink struct {
// URL to a page with more information about the error
Url string `json:"url"`
// Human readable error message
Message string `json:"message"`
}
// NewCheckErrorLink creates a new CheckErrorLink object.
func NewCheckErrorLink() *CheckErrorLink {
return &CheckErrorLink{}
}
// +k8s:openapi-gen=true
type CheckReportFailure struct {
// Severity of the failure
Severity CheckReportFailureSeverity `json:"severity"`
// Step ID that the failure is associated with
StepID string `json:"stepID"`
// Human readable identifier of the item that failed
Item string `json:"item"`
// Links to actions that can be taken to resolve the failure
Links []CheckErrorLink `json:"links"`
}
// 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{}
}

View File

@@ -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{}

View File

@@ -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{}
}

View File

@@ -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{}

View File

@@ -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

View File

@@ -1,27 +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"`
Resolution string `json:"resolution"`
}
// 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{}
}

View File

@@ -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"
)

View File

@@ -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,
}
)

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":{"item":{"description":"Human readable identifier of the item that failed","type":"string"},"links":{"description":"Links to actions that can be taken to resolve the failure","items":{"properties":{"message":{"description":"Human readable error message","type":"string"},"url":{"description":"URL to a page with more information about the error","type":"string"}},"required":["url","message"],"type":"object"},"type":"array"},"severity":{"description":"Severity of the failure","enum":["high","low"],"type":"string"},"stepID":{"description":"Step ID that the failure is associated with","type":"string"}},"required":["severity","stepID","item","links"],"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"},"resolution":{"type":"string"},"stepID":{"type":"string"},"title":{"type":"string"}},"required":["title","description","stepID","resolution"],"type":"object"},"type":"array"}},"required":["name","steps"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
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")
}

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(),
},
}
}

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.HasRole(identity.RoleAdmin) {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionDeny, "forbidden", nil
})
}

View File

@@ -1,82 +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
}
func (m *mockUser) HasRole(role identity.RoleType) bool {
return role == identity.RoleAdmin && m.isGrafanaAdmin
}
// Implement other methods of identity.Requester as needed

View File

@@ -1,66 +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
StackID string
}

View File

@@ -1,177 +0,0 @@
package datasourcecheck
import (
"context"
"errors"
"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/infra/log"
"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
log log.Logger
}
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,
log: log.New("advisor.datasourcecheck"),
}
}
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,
log: c.log,
},
}
}
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 "Checks if the UID of a data source is valid."
}
func (s *uidValidationStep) Resolution() string {
return "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 or delete the data source and create a new one."
}
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,
s.ID(),
fmt.Sprintf("%s (%s)", ds.Name, ds.UID),
[]advisor.CheckErrorLink{},
), nil
}
return nil, nil
}
type healthCheckStep struct {
PluginContextProvider pluginContextProvider
PluginClient plugins.Client
log log.Logger
}
func (s *healthCheckStep) Title() string {
return "Health check"
}
func (s *healthCheckStep) Description() string {
return "Checks if a data sources is healthy."
}
func (s *healthCheckStep) Resolution() string {
return "Go to the data source configuration page and address the issues reported."
}
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 {
// Unable to check health check
s.log.Error("Failed to get plugin context", "datasource_uid", ds.UID, "error", err)
return nil, nil
}
req := &backend.CheckHealthRequest{
PluginContext: pCtx,
Headers: map[string]string{},
}
resp, err := s.PluginClient.CheckHealth(ctx, req)
if err != nil || resp.Status != backend.HealthStatusOk {
if err != nil {
s.log.Debug("Failed to check health", "datasource_uid", ds.UID, "error", err)
if errors.Is(err, plugins.ErrMethodNotImplemented) || errors.Is(err, plugins.ErrPluginUnavailable) {
// The plugin does not support backend health checks
return nil, nil
}
} else {
s.log.Debug("Failed to check health", "datasource_uid", ds.UID, "status", resp.Status, "message", resp.Message)
}
return checks.NewCheckReportFailure(
advisor.CheckReportFailureSeverityHigh,
s.ID(),
ds.Name,
[]advisor.CheckErrorLink{
{
Message: "Fix me",
Url: fmt.Sprintf("/connections/datasources/edit/%s", ds.UID),
},
},
), nil
}
return nil, nil
}
type pluginContextProvider interface {
GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error)
}

View File

@@ -1,188 +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/infra/log"
"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,
log: log.New("advisor.datasourcecheck"),
}
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,
log: log.New("advisor.datasourcecheck"),
}
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, "uid-validation", failures[0].StepID)
})
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,
log: log.New("advisor.datasourcecheck"),
}
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", failures[0].StepID)
})
t.Run("should skip health check when plugin does not support backend health checks", 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{err: plugins.ErrMethodNotImplemented}
check := &check{
DatasourceSvc: mockDatasourceSvc,
PluginContextProvider: mockPluginContextProvider,
PluginClient: mockPluginClient,
log: log.New("advisor.datasourcecheck"),
}
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, 0)
})
}
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
err error
}
func (m *MockPluginClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
return m.res, m.err
}

View File

@@ -1,31 +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
// Explains the action that needs to be taken to resolve the issue
Resolution() string
// Run executes the step for an item and returns a report
Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error)
}

View File

@@ -1,199 +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) Resolution() string {
return "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do'" +
"target=_blank>documentation</a> for recommended steps or delete the plugin."
}
func (s *deprecationStep) ID() string {
return "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,
s.ID(),
p.ID,
[]advisor.CheckErrorLink{
{
Message: "Admin",
Url: fmt.Sprintf("/plugins/%s", 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 "Checks if an installed plugins has a newer version available."
}
func (s *updateStep) Resolution() string {
return "Go to the plugin admin page and upgrade to the latest version."
}
func (s *updateStep) ID() string {
return "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,
s.ID(),
p.ID,
[]advisor.CheckErrorLink{
{
Message: "Upgrade",
Url: fmt.Sprintf("/plugins/%s?page=version-history", 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
}

View File

@@ -1,210 +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,
StepID: "deprecation",
Item: "plugin1",
Links: []advisor.CheckErrorLink{
{
Url: "/plugins/plugin1",
Message: "Admin",
},
},
},
},
},
{
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,
StepID: "update",
Item: "plugin2",
Links: []advisor.CheckErrorLink{
{
Url: "/plugins/plugin2?page=version-history",
Message: "Upgrade",
},
},
},
},
},
{
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,
StepID: "update",
Item: "plugin2",
Links: []advisor.CheckErrorLink{
{
Url: "/plugins/plugin2?page=version-history",
Message: "Upgrade",
},
},
},
},
},
{
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
}

View File

@@ -1,40 +0,0 @@
package checks
import (
"fmt"
"strconv"
"github.com/grafana/authlib/types"
advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
TypeLabel = "advisor.grafana.app/type"
StatusAnnotation = "advisor.grafana.app/status"
)
func NewCheckReportFailure(
severity advisor.CheckReportFailureSeverity,
stepID string,
item string,
links []advisor.CheckErrorLink,
) *advisor.CheckReportFailure {
return &advisor.CheckReportFailure{
Severity: severity,
StepID: stepID,
Item: item,
Links: links,
}
}
func GetNamespace(stackID string) (string, error) {
if stackID == "" {
return metav1.NamespaceDefault, nil
}
stackId, err := strconv.ParseInt(stackID, 10, 64)
if err != nil {
return "", fmt.Errorf("invalid stack id: %s", stackID)
}
return types.CloudNamespaceFormatter(stackId), nil
}

View File

@@ -1,46 +0,0 @@
package checks
import (
"testing"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestGetNamespace(t *testing.T) {
tests := []struct {
name string
input string
expected string
expectedErr string
}{
{
name: "empty stack ID",
input: "",
expected: metav1.NamespaceDefault,
},
{
name: "valid stack ID",
input: "1234567890",
expected: "stacks-1234567890",
},
{
name: "invalid stack ID",
input: "invalid",
expected: "",
expectedErr: "invalid stack id: invalid",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := GetNamespace(tt.input)
if tt.expectedErr != "" {
assert.EqualError(t, err, tt.expectedErr)
} else {
assert.NoError(t, err)
}
assert.Equal(t, tt.expected, result)
})
}
}

View File

@@ -1,225 +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
namespace string
}
// 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
}
namespace, err := checks.GetNamespace(specificConfig.StackID)
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,
namespace: namespace,
}, 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, r.namespace, 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: r.namespace,
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, r.namespace, 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
}

View File

@@ -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
}

View File

@@ -1,91 +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"
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
"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
namespace string
}
// 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
namespace, err := checks.GetNamespace(specificConfig.StackID)
if err != nil {
return nil, err
}
// 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,
namespace: namespace,
}, 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(),
Resolution: s.Resolution(),
}
}
obj := &advisorv0alpha1.CheckType{
ObjectMeta: metav1.ObjectMeta{
Name: t.ID(),
Namespace: r.namespace,
},
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
}

View File

@@ -1,196 +0,0 @@
package checktyperegisterer
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"
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"),
},
{
name: "custom namespace",
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) {
if obj.GetNamespace() != "custom-namespace" {
return nil, fmt.Errorf("expected namespace %s, got %s", "custom-namespace", obj.GetNamespace())
}
return obj, nil
},
expectedErr: nil,
},
}
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,
},
namespace: "custom-namespace",
}
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 {
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
}
func (m *mockStep) Resolution() string {
return ""
}
func (m *mockStep) Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error) {
return nil, nil
}
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)
}

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
}

View File

@@ -1,200 +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) Resolution() string {
return "mock"
}
func (m *mockStep) ID() string {
return "mock"
}

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

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
)
@@ -32,13 +32,13 @@ require (
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.7.0 // 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/pkg/apimachinery v0.0.0-20250220154326-6e5de80ef295 // 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
@@ -74,7 +74,7 @@ require (
go.uber.org/zap v1.27.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.35.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.29.0 // indirect
@@ -83,13 +83,13 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.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

View File

@@ -60,8 +60,8 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
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.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
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=
@@ -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-20250220154326-6e5de80ef295 h1:bOKkAzmkCnK2EN0LGsHoq5HyfXMLKXrr8+q35Fh+XQI=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250220154326-6e5de80ef295/go.mod h1:1iWqntBW91TsiyqneHrqTFV12vd1Tei+f5VY2ovkNAo=
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=
@@ -223,8 +224,8 @@ 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.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
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.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
@@ -269,8 +270,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/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=
@@ -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=

View File

@@ -0,0 +1,3 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --kindgrouping=group --postprocess --crdencoding none

View File

@@ -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
@@ -27,14 +27,13 @@ require (
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.7.0 // 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,28 +42,25 @@ 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.35.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/oauth2 v0.27.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
@@ -73,12 +69,12 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
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

View File

@@ -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=
@@ -40,26 +38,24 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
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.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
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.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,15 +143,13 @@ 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.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
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=
@@ -181,8 +167,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
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=
@@ -195,8 +179,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/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=
@@ -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=

View File

@@ -0,0 +1,2 @@
module: "github.com/grafana/grafana/apps/investigation/kinds"
language: version: "v0.8.2"

View File

@@ -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
}

View File

@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
package v0alpha1
package v1alpha1
import (
"encoding/json"

View File

@@ -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"`
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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,24 +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.CheckErrorLink": schema_pkg_apis_advisor_v0alpha1_CheckErrorLink(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.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{
@@ -58,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"),
},
},
},
@@ -72,320 +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_CheckErrorLink(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{
"url": {
"from": {
SchemaProps: spec.SchemaProps{
Description: "URL to a page with more information about the error",
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: "",
},
},
"message": {
"maxLines": {
SchemaProps: spec.SchemaProps{
Description: "Human readable error message",
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{"url", "message"},
Required: []string{"datasource", "expr", "refId"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryMetrics(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Description: "DataQueryMetrics is a data query for metrics.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
"datasource": {
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: "",
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: "",
},
},
"stepID": {
SchemaProps: spec.SchemaProps{
Description: "Step ID that the failure is associated with",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"item": {
SchemaProps: spec.SchemaProps{
Description: "Human readable identifier of the item that failed",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"links": {
SchemaProps: spec.SchemaProps{
Description: "Links to actions that can be taken to resolve the failure",
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.CheckErrorLink"),
},
},
},
},
},
},
Required: []string{"severity", "stepID", "item", "links"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckErrorLink"},
}
}
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: "",
@@ -393,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",
@@ -451,165 +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: "",
},
},
"resolution": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"title", "description", "stepID", "resolution"},
},
},
}
}
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",
@@ -632,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"},
},

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")
}

View File

@@ -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()},
}
}

View File

@@ -1,3 +0,0 @@
.PHONY: generate
generate:
@grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none

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
}
}
]

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
}

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