Compare commits

...

85 Commits

Author SHA1 Message Date
Karl Persson
64017e8ca6 Security: Omit error from http response when user does not exists (#639) 2022-11-08 11:38:42 +01:00
Karl Persson
f8239a2157 Security fix for privilege escalation (#640)
* Trim leading and trailing whitespaces from email and username on signup

* Check whether the provided email address is the same as where the invitation sent

Co-authored-by: Mihaly Gyongyosi <mgyongyosi@users.noreply.github.com>
2022-11-08 11:38:29 +01:00
Emil Tullstedt
c8bd372532 pkg/web: Avoid shared middleware slice 2022-11-08 11:33:49 +01:00
Grot (@grafanabot)
164fb230cb Docs: corrects outer join example (#58348) (#58366)
* corrects outer join example

* Update docs/sources/panels-visualizations/query-transform-data/transform-data/index.md

* adds query tables back in

(cherry picked from commit 0315f6317e)

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
2022-11-07 13:53:18 -06:00
Dimitris Sotirakis
7382b1be90 [v9.2.x] CI: Use full dockerhub repository name (#57979) (#57983)
* CI: Use full `dockerhub` repository name (#57979)

* Add full dockerhub repo name

* Update grabpl version

(cherry picked from commit 57ee0e4a4b)

* sign drone.yml

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-11-07 18:23:44 +01:00
George Robinson
d38ac63f22 Alerting: Append org ID to alert notification URLs (#57123) (#58349)
(cherry picked from commit db1fd10ff1)

Co-authored-by: Neel <47709856+neel1996@users.noreply.github.com>
2022-11-07 17:07:07 +00:00
Grot (@grafanabot)
67f503b820 Alerting: Fix test fails in some environments (#58251) (#58356)
(cherry picked from commit 8353f307aa)

Co-authored-by: George Robinson <george.robinson@grafana.com>
2022-11-07 16:54:39 +00:00
Zoltán Bedi
4ec37fb058 MSSql/Postgres: Fix visual query editor filter disappearing (#58248) (#58354)
(cherry picked from commit b472306239)
2022-11-07 17:35:49 +01:00
Grot (@grafanabot)
4fee0645a1 Datasource Loki: preserve header X-ID-Token (#57878) (#58346)
(cherry picked from commit bc280d0749)

Co-authored-by: Si Mon <85333972+siiimooon@users.noreply.github.com>
2022-11-07 11:11:10 -05:00
Emil Tullstedt
b03e28fc60 Chore: Upgrade Go to 1.19.3 (v9.2) (#58339) 2022-11-07 16:52:15 +01:00
Grot (@grafanabot)
db55065687 fix thanos semver string (#58335) (#58344)
(cherry picked from commit 6bc8ec0f9b)

Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
2022-11-07 09:46:37 -06:00
Grot (@grafanabot)
7ca5c227dd Toolkit: Fix Webpack less-loader config (#57950) (#58175)
(cherry picked from commit b799be3052)

Co-authored-by: dessen-xu <1805680163@qq.com>
2022-11-07 16:16:58 +01:00
Grot (@grafanabot)
3dc8434cf4 @grafana/e2e: Fix addPanel for small screen size (#57398) (#58314)
(cherry picked from commit d001a1b035)

Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
2022-11-07 07:06:23 -05:00
Grot (@grafanabot)
8cb58c1560 Chore: Disable dashboard-time-zone e2e tests (#58320) (#58323)
(cherry picked from commit d4e3d47f56)

Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
2022-11-07 06:47:43 -05:00
Grot (@grafanabot)
63f6207a1f Auth: Check for OrgUsersAdd on frontend to display pending invites (#58217) (#58225)
(cherry picked from commit 9ff2765bb9)

Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
2022-11-07 06:28:57 -05:00
Grot (@grafanabot)
97ee2cf918 MySQL: make it possible to add CA cert without using tlsAuth (#58226) (#58308)
(cherry picked from commit b1bfae0350)

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
2022-11-07 03:54:50 -05:00
Grot (@grafanabot)
b642a797fd Timeseries: Fix null pointer when matching fill below to field (#58030) (#58298)
* Fix timeseries fill below to error

* wip

* modifications

* add tests for fillBelowTo option

(cherry picked from commit d673c8809b)

Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com>
2022-11-06 09:35:06 -05:00
Eric Leijonmarck
9b07bc7e98 merge complete (#58274)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2022-11-04 15:03:07 -07:00
Eric Leijonmarck
94594d61e6 followup fix for backport (#58273) 2022-11-04 21:20:20 +00:00
Eric Leijonmarck
0026764f04 merge complete (#58272) 2022-11-04 20:45:38 +00:00
Grot (@grafanabot)
a09a23c8bf Search: Fixes searching by current folder when opened by clicking dashboard folder name (#57716) (#57949)
* Search: Read from url on mount no on app boot

* Fixed tests

* Remove unused type

(cherry picked from commit 3991be4c1d)

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2022-11-04 12:57:39 -04:00
Grot (@grafanabot)
e4af9fba96 Build: add explicit build step for go codeql (#58195) (#58243)
* add explicit build step for go codeql

* support workflow_dispatch for codeql checks

* syntax fix

* enable on push to codeql-go branch

* test

* use go version from go.mod

* explicitly set go version

* tidy up, add workflow_dispatch support to all codeql actions

(cherry picked from commit da9c646f24)

Co-authored-by: Dan Cech <dcech@grafana.com>
2022-11-04 11:40:40 -04:00
Grot (@grafanabot)
f70d51c2c6 [v9.2.x] Alerting: Encode path separators to side-step proxies (#58222)
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2022-11-04 07:13:53 -04:00
Grot (@grafanabot)
b8835eba17 fixes typo (#58159) (#58194)
(cherry picked from commit 1722000309)

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
2022-11-03 13:55:51 -05:00
Grot (@grafanabot)
4e2d4c42f0 fixed explain handlers for label- and lineformat (#58135) (#58151)
(cherry picked from commit 4b1ddba0a8)

Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>
2022-11-03 10:09:47 -04:00
Grot (@grafanabot)
ac66ba77da TimeSeries: more thorough detection of negative values for stacking dir (#57863) (#58147)
(cherry picked from commit 4d88e2b542)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
2022-11-03 09:38:19 -04:00
Grot (@grafanabot)
afab41a9c4 reduce the number of requests in folder section (#55876) (#58145)
(cherry picked from commit 372ba83534)

Co-authored-by: Marcos Vinicius <marcos.vinicius.wz@gmail.com>
2022-11-03 09:35:39 -04:00
Piotr Jamróz
72cf8605c0 [v9.2.x] Explore: Track data links usage (#56868) (#58037)
* Explore: Track data links usage (#56868)

* Add tracking for data links in explore

* Add tracking for data links in explore

* Fix tests

* Retrigger build

(cherry picked from commit dd5e3a0818)

# Conflicts:
#	public/app/features/explore/Explore.tsx
#	public/app/features/explore/LogsContainer.tsx

* Post-merge fixes

Remove unused import
2022-11-03 14:22:40 +01:00
Grot (@grafanabot)
7ba1e9e258 Tempo: Make usage of time range for TraceID query optional (#58057) (#58128)
* Added switch to toggle the TraceID query time shift

* Fix and improve tests

(cherry picked from commit 90ac300d10)

Co-authored-by: Andre Pereira <adrapereira@gmail.com>
2022-11-03 07:18:12 -04:00
Grot (@grafanabot)
f07841db8a increase select placeholder contrast to be WCAG AA compliant (#58034) (#58125)
(cherry picked from commit c3206167a6)

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
2022-11-03 07:00:45 -04:00
Eric Leijonmarck
797dd2dd58 fix: migration of alert_rules fix (#58123) 2022-11-03 10:37:22 +00:00
George Robinson
ab3718afba Alerting: Fix screenshot is not taken for stale series (#57982) (#58102)
(cherry picked from commit 215ffee437)
2022-11-03 10:17:01 +00:00
Grot (@grafanabot)
d1df696c31 Alerting: Fix feedback (#57922) (#58104)
(cherry picked from commit f2e4cb7c4e)

Co-authored-by: George Robinson <george.robinson@grafana.com>
2022-11-02 18:49:29 -04:00
Grot (@grafanabot)
dfeb978e3b remove unneeded package updates (#58005) (#58068)
(cherry picked from commit 6a4a10fa92)

Co-authored-by: Dan Cech <dcech@grafana.com>
2022-11-02 18:31:43 +00:00
Torkel Ödegaard
8b7664294c LibrayPanels: Fix unlinking libray panel (#57825) (#58042) 2022-11-02 16:19:53 +01:00
Grot (@grafanabot)
5895100beb Alerting: Fix response is not returned for invalid Duration in Provisioning API (#58046) (#58049)
(cherry picked from commit 4c581b5f85)

Co-authored-by: George Robinson <george.robinson@grafana.com>
2022-11-02 13:06:58 +00:00
Grot (@grafanabot)
844b08962d chore: bump code coverage action version (#56710) (#58040)
(cherry picked from commit e3e32c7d04)

Co-authored-by: Giordano Ricci <me@giordanoricci.com>
2022-11-02 12:18:01 +00:00
Dimitris Sotirakis
551c4aa562 Linux Packages: Handle publish to beta (#57528) (#58044)
Uses the feature added here: https://github.com/grafana/deployment_tools/pull/46301
When a version is named "beta", it will be distributed in the beta distribution, rather than in stable

Co-authored-by: dsotirakis <dimitrios.sotirakis@grafana.com>
(cherry picked from commit c46a4a0b26)

Co-authored-by: Julien Duchesne <julien.duchesne@grafana.com>
2022-11-02 14:17:44 +02:00
Andres Martinez Gotor
1ac0c03a1d [v9.2.x] Google Cloud Monitoring: Set frame interval to draw null values (#57914) 2022-11-02 12:14:30 +01:00
Grot (@grafanabot)
484b098a20 Alerting: Fix flaky test in notifiers (#57927) (#57993)
* Alerting: Fix flaky test in notifiers

* remove TODO comment

(cherry picked from commit a3f828de8a)

Co-authored-by: Santiago <santiagohernandez.1997@gmail.com>
2022-11-01 12:29:24 -03:00
Grot (@grafanabot)
ca73c43b56 metrics: expose when the binary was built as an gauge (#57951) (#57969)
Signed-off-by: bergquist <carl.bergquist@gmail.com>
(cherry picked from commit 3188af9be3)
2022-11-01 08:14:17 -04:00
Grot (@grafanabot)
6c027ccf6a "Release: Updated versions in package to 9.2.4" (#57958) 2022-11-01 06:50:30 -04:00
Grot (@grafanabot)
0275f11785 Changelog: Updated changelog for 9.2.3 (#57955) (#57957)
(cherry picked from commit 02add89b53)
2022-11-01 06:39:10 -04:00
Dimitris Sotirakis
3274e8727e Add GCP_KEY to publish-grafanacom step (#57910) (#57948)
(cherry picked from commit 1eaf7cbfc0)
2022-11-01 09:07:44 +00:00
Grot (@grafanabot)
522a819e9e CloudWatch: Fix all-log-groups endpoint when called without logGroupNamePrefix (#57483) (#57945)
(cherry picked from commit 1f7c84f125)

Co-authored-by: Lion Ralfs <lion.ralfs@gmail.com>
2022-11-01 09:14:36 +01:00
Grot (@grafanabot)
f6abf640eb TimeSeries: Render null-bounded points at data edges (#57798) (#57938)
(cherry picked from commit 45234e76eb)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
2022-10-31 19:06:43 -04:00
Grot (@grafanabot)
47b635270e BarChart: Fix stacked hover (#57711) (#57937)
(cherry picked from commit fbfd0fd51b)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
2022-10-31 17:58:45 -04:00
Grot (@grafanabot)
36bfb144b7 removes CTAs (#57931) (#57935)
(cherry picked from commit 6aa3003a54)

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
2022-10-31 16:39:58 -05:00
Grot (@grafanabot)
fade9fb6ae [v9.2.x] Alerting: fix filtering in notification policies (#57925)
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2022-10-31 13:53:33 -04:00
Grot (@grafanabot)
ad2ea44977 Attempt to preserve UID from migrated channel (#57639) (#57919)
(cherry picked from commit 0dfd78c88c)

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
2022-10-31 12:17:48 -05:00
Grot (@grafanabot)
924180a25b Alerting: Add debug logs in validateAndGetPrefix (#57002) (#57923)
(cherry picked from commit b0a927b138)

Co-authored-by: George Robinson <george.robinson@grafana.com>
2022-10-31 17:12:19 +00:00
Grot (@grafanabot)
76ed60064d change json command parameter names from userID to userId and teamID to teamId (#57902) (#57913)
(cherry picked from commit 5c1a1c8318)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2022-10-31 15:33:39 +00:00
Grot (@grafanabot)
e09307c078 add an endpoint for updating several managed permissions with one call (#57893) (#57898)
(cherry picked from commit 2546437e20)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2022-10-31 14:31:34 +00:00
Grot (@grafanabot)
ec9c2ed029 Google Cloud Monitoring: Ensure selectors fit in the screen (#57817) (#57899)
(cherry picked from commit ce38840f29)

Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
2022-10-31 13:36:07 +01:00
Grot (@grafanabot)
92b10cc965 Chore: Update footer changelog link to github (#57871) (#57895)
(cherry picked from commit fd5c147574)

Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
2022-10-31 08:33:25 -04:00
Grot (@grafanabot)
3be1ddc56a CloudWatch: Fix broken test (#57879) (#57900)
* mock date.now

* fix broken test

(cherry picked from commit 92ed9a4f2f)

Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
2022-10-31 08:16:12 -04:00
Grot (@grafanabot)
dac165a7fc RBAC: Allow to list users for dashboard / folder admins (#57080) (#57252)
* RBAC: Use query struct in tests

* RBAC: If access control enforcement is disabled don't filter out users
when fetching permissions

(cherry picked from commit 9adaf1565c)

Co-authored-by: Karl Persson <kalle.persson@grafana.com>
2022-10-31 07:31:43 -04:00
Grot (@grafanabot)
44655b96cb docs(config): Include admin_email documentation (#55789) (#57725)
(cherry picked from commit 1340c2c358)

Co-authored-by: Pepe Fagoaga <pepe@verica.io>
2022-10-31 11:39:48 +01:00
Grot (@grafanabot)
79104ef556 Access Control: documentation for RBAC provisioning with Terraform (#57747) (#57882)
* add docs for RBAC provisioning with Terraform

* remove unnecessary bit

* shuffle the structure around, as docs can't go more than four levels deep

* Update index.md

* Update index.md

(cherry picked from commit 7e62352aea)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2022-10-31 10:36:13 +00:00
Grot (@grafanabot)
95189820fe Docs: Add information about DB version support to upgrade guide. (#57643) (#57868)
In v9.2 Grafana added an official DB version support policy. That change
is now noted in the upgrade guide.

(cherry picked from commit 89d917b196)

Co-authored-by: Joe Blubaugh <joe.blubaugh@grafana.com>
2022-10-31 09:27:30 +01:00
Grot (@grafanabot)
68d7dadaec Dashboards: Add workaround for react-grid-layout rearrange bug (#57832) (#57836)
(cherry picked from commit e4d1d8d70c)

Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
2022-10-29 23:46:57 +01:00
Grot (@grafanabot)
2bfc106473 Dashboards: Add workaround for react-grid-layout rearrange bug (#57832) (#57836)
(cherry picked from commit e4d1d8d70c)

Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
2022-10-29 23:46:46 +01:00
Christopher Moyer
82430165ee resolves merge conflicts (#57840) 2022-10-28 13:57:12 -05:00
Grot (@grafanabot)
85f1aab363 Prometheus: Chore - Remove incorrect FrameType from exemplar frame (#57695) (#57828)
(cherry picked from commit 2cd9cbd359)

Co-authored-by: Kyle Brandt <kyle@grafana.com>
2022-10-28 10:53:36 -04:00
Grot (@grafanabot)
3df51bf025 Prometheus: Do not drop errors in streaming parser (#57698) (#57835)
- Fixes #57692
- and also takes care of #42776 when using the streaming parser, not an ideal fix for #42776 but makes explore work better I think. https://github.com/grafana/grafana/issues/57365 might be a better longer term solution

(cherry picked from commit 6126f56ef0)

Co-authored-by: Kyle Brandt <kyle@grafana.com>
2022-10-28 10:52:36 -04:00
Grot (@grafanabot)
b1d914bceb Remove Sensu from docs (#57812) (#57823)
We do not support Sensu in Grafana Alerting, only Sensu Go.

(cherry picked from commit ee7adc081b)

Co-authored-by: Armand Grillet <2117580+armandgrillet@users.noreply.github.com>
2022-10-28 13:59:15 +02:00
Marcus Andersson
e0e74ea6d2 [v9.2.x] Chore: Fix vulnerabilities in webpack loader-utils (#57753)
* chore: remove unused webpack loaders from core and toolkit

* chore: refresh yarn.lock file

* getting there...I hope..

* making sure we are not using naughty loader-utils.

* fixed storybook.
2022-10-28 13:00:04 +02:00
Grot (@grafanabot)
b94c64ef48 CI: Add CreateTempDir func and use it in publish packages logic (#57171) (#57261)
* Add CreateTempDir func and use it in publish packages logic

* Fill err return in defer func

(cherry picked from commit e829b50149)

Co-authored-by: Dimitris Sotirakis <dimitrios.sotirakis@grafana.com>
2022-10-28 05:43:05 -04:00
Grot (@grafanabot)
43d3f21ff0 Only provide version ot build-frontend-packages if it's a valid semver (has 2 digits) (#57808) (#57810)
(cherry picked from commit fd16cad7da)

Co-authored-by: Kevin Minehart <kmineh0151@gmail.com>
2022-10-28 11:26:22 +02:00
emerson_gong
a62cb4e6c1 Security: Upgrade x/text to version unaffected by CVE-2022-32149 (#57797) 2022-10-28 09:07:27 +02:00
Grot (@grafanabot)
23b791c234 TimeseriesPanel: Fill below to override works with name override (#57728) (#57800)
(cherry picked from commit 953fdfe76f)

Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com>
2022-10-28 02:46:35 -04:00
Grot (@grafanabot)
0b27b6a8c2 Candlestick: Maintain candle width at different display resolutions (#57709) (#57794)
(cherry picked from commit 7d020d3f6e)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
2022-10-27 19:45:58 -05:00
ismail simsek
e71e6ae07e Prometheus: fix Raw query is not updated when label op change. (#57492) (#57493) (#57780)
(cherry picked from commit 9aac0d32f9)

Co-authored-by: yinjialu <37073056+yinjialu@users.noreply.github.com>
2022-10-27 14:24:07 -04:00
Grot (@grafanabot)
2576f05029 Alerting: Fix "Not Implemented" responses (#57710) (#57712) 2022-10-27 14:48:54 -03:00
Grot (@grafanabot)
e8cff14164 [v9.2.x] Alerting: Fall back to "range" query type for unified alerting when "both" is specified (#57765)
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2022-10-27 11:36:36 -04:00
Jo
a162fdf32f fix GF_AUTH_JWT_URL_LOGIN not working (#57689) (#57761)
(cherry picked from commit cae900c6f9)
2022-10-27 10:44:50 -04:00
Grot (@grafanabot)
99f6606285 Fix: Unlock new button based on user permissions (#57733) (#57760)
(cherry picked from commit 4d380978d3)

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
2022-10-27 16:03:20 +02:00
Grot (@grafanabot)
d2f721c18e Docs: (Whats new 9.2) Prom Stream Parser (#57603) (#57693)
* Docs: (Whats new 9.2) Prom Stream Parser

* Update docs/sources/whatsnew/whats-new-in-v9-2.md

Co-authored-by: Garrett Guillotte <100453168+gguillotte-grafana@users.noreply.github.com>

Co-authored-by: Garrett Guillotte <100453168+gguillotte-grafana@users.noreply.github.com>
(cherry picked from commit dfdc9bcbc1)

Co-authored-by: Kyle Brandt <kyle@grafana.com>
2022-10-26 13:26:48 -04:00
Grot (@grafanabot)
efd139ecf3 Prometheus query builder: Replace select with AsyncSelect to support high cardinality prometheus instances (#57300) (#57630)
* Replace current select with AsyncSelect component to facilitate autocomplete via prometheus server instead of client application
Co-authored-by: Kyle Brandt <kyle@grafana.com>

(cherry picked from commit c27aac0d38)

Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
2022-10-26 08:10:30 -05:00
Galen Kistler
5647a981ed Prometheus: Flavor/version configuration (#57554) (#57563)
* Backport PR for: Prometheus: Flavor/version configuration (#57554), and /label match parameter support #56510

* Revert "Revert "Prometheus: Type and flavor configuration (#56496)" (#57552)"
This reverts commit 2432ce619a.
* Adds new fields and documentation for Prometheus datasource configuration: prometheus type, and version

(cherry picked from commit f93c3acc51)

* Revert "Revert "Prometheus: Provide label values match parameter API when supported prometheus instance is configured (#56510)" (#57551)" (#57553) (#57564)

This reverts commit e7671bf909.
(cherry picked from commit e59ddd6bc5)
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>

Co-authored-by: Grot (@grafanabot) <43478413+grafanabot@users.noreply.github.com>
2022-10-26 08:10:05 -05:00
Grot (@grafanabot)
d6f248c14e move data source permission model to enterprise repo (#57615) (#57659)
(cherry picked from commit 92531c5596)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2022-10-26 13:30:20 +01:00
Grot (@grafanabot)
f58d6107e1 [v9.2.x] Alerting: Always allow configuring AM configuration (#57614)
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2022-10-25 11:11:05 -04:00
Grot (@grafanabot)
b3a46212df "Release: Updated versions in package to 9.2.3" (#57605) 2022-10-25 15:08:27 +02:00
Grot (@grafanabot)
3289770198 Changelog: Updated changelog for 9.2.2 (#57601) (#57604)
(cherry picked from commit f64b0e1fae)
2022-10-25 14:45:07 +02:00
Grot (@grafanabot)
8d7c3f19ee live: explicitely reply with http 200 (#57428) (#57592)
`pkg/web` triggers a panic when a http handler chain does not return any
response to the client.
This has been put in place, because it usually means a middleware along
the way did not call the next one.

In this specific case however, the handlers meant to return 200, but did
not do so explicitely, instead relying on the default behavior of `net/http`

(cherry picked from commit beaaabd770)

Co-authored-by: sh0rez <me@shorez.de>
2022-10-25 06:02:15 -04:00
244 changed files with 3808 additions and 3344 deletions

View File

@@ -7416,8 +7416,7 @@ exports[`better eslint`] = {
],
"public/app/plugins/datasource/prometheus/querybuilder/state.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/plugins/datasource/prometheus/querybuilder/state.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ on:
jobs:
workflow-call:
uses: grafana/code-coverage/.github/workflows/code-coverage.yml@v0.1.11
uses: grafana/code-coverage/.github/workflows/code-coverage.yml@v0.1.12
with:
frontend-path-regexp: public\/app\/plugins\/datasource\/(grafana-azure-monitor-datasource|cloud-monitoring|cloudwatch)
backend-path-regexp: pkg\/tsdb\/(azuremonitor|cloudmonitoring|cloudwatch)

View File

@@ -6,6 +6,7 @@
name: "CodeQL"
on:
workflow_dispatch:
push:
branches: [main, v1.8.x, v2.0.x, v2.1.x, v2.6.x, v3.0.x, v3.1.x, v4.0.x, v4.1.x, v4.2.x, v4.3.x, v4.4.x, v4.5.x, v4.6.x, v4.7.x, v5.0.x, v5.1.x, v5.2.x, v5.3.x, v5.4.x, v6.0.x, v6.1.x, v6.2.x, v6.3.x, v6.4.x, v6.5.x, v6.6.x, v6.7.x, v7.0.x, v7.1.x, v7.2.x]
paths-ignore:
@@ -39,6 +40,12 @@ jobs:
# a pull request then we can checkout the head.
fetch-depth: 2
- if: matrix.language == 'go'
name: Set go version
uses: actions/setup-go@v3
with:
go-version: '1.19.2'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -49,5 +56,11 @@ jobs:
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- if: matrix.language == 'go'
name: Build go files
run: |
go mod verify
make build-go
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -11,7 +11,7 @@ on:
jobs:
workflow-call:
uses: grafana/code-coverage/.github/workflows/code-coverage.yml@v0.1.11
uses: grafana/code-coverage/.github/workflows/code-coverage.yml@v0.1.12
with:
frontend-path-regexp: public\/app\/features\/(explore|correlations)
backend-path-regexp: pkg\/services\/(queryhistory)

View File

@@ -1,6 +1,7 @@
name: "CodeQL for PR / go"
on:
workflow_dispatch:
pull_request:
branches: [main]
paths:
@@ -19,11 +20,21 @@ jobs:
# a pull request then we can checkout the head.
fetch-depth: 2
- name: Set go version
uses: actions/setup-go@v3
with:
go-version: '1.19.2'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: "go"
- name: Build go files
run: |
go mod verify
make build-go
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -1,6 +1,7 @@
name: "CodeQL for PR / javascript"
on:
workflow_dispatch:
pull_request:
branches: [main]
paths:

View File

@@ -1,6 +1,7 @@
name: "CodeQL for PR / python"
on:
workflow_dispatch:
pull_request:
branches: [main]
paths:

View File

@@ -62,7 +62,7 @@ var config = {
url: '${HOST}/login',
wait: 500,
rootElement: '.main-view',
threshold: 12,
threshold: 13,
},
{
url: '${HOST}/login',
@@ -74,7 +74,7 @@ var config = {
"click element button[aria-label='Login button']",
"wait for element [aria-label='Skip change password button'] to be visible",
],
threshold: 13,
threshold: 14,
rootElement: '.main-view',
},
{
@@ -101,49 +101,49 @@ var config = {
rootElement: '.main-view',
// the unified alerting promotion alert's content contrast is too low
// see https://github.com/grafana/grafana/pull/41829
threshold: 5,
threshold: 6,
},
{
url: '${HOST}/datasources',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
{
url: '${HOST}/org/users',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
{
url: '${HOST}/org/teams',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
{
url: '${HOST}/plugins',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
{
url: '${HOST}/org',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
{
url: '${HOST}/org/apikeys',
wait: 500,
rootElement: '.main-view',
threshold: 3,
threshold: 4,
},
{
url: '${HOST}/dashboards',
wait: 500,
rootElement: '.main-view',
threshold: 0,
threshold: 1,
},
],
};

View File

@@ -60,9 +60,6 @@ packageExtensions:
react-simple-compat: 1.2.2
peerDependencies:
framework-utils: ^1.1.0
react-docgen-typescript-loader@3.7.2:
peerDependencies:
webpack: 4.41.5
react-icons@2.2.7:
peerDependencies:
prop-types: "*"

View File

@@ -1,3 +1,83 @@
<!-- 9.2.3 START -->
# 9.2.3 (2022-10-31)
### Features and enhancements
- **Docs:** Add information about DB version support to upgrade guide. [#57643](https://github.com/grafana/grafana/pull/57643), [@joeblubaugh](https://github.com/joeblubaugh)
- **Footer:** Update footer release notes link to Github changelog. [#57871](https://github.com/grafana/grafana/pull/57871), [@joshhunt](https://github.com/joshhunt)
- **Prometheus:** Do not drop errors in streaming parser. [#57698](https://github.com/grafana/grafana/pull/57698), [@kylebrandt](https://github.com/kylebrandt)
- **Prometheus:** Flavor/version configuration. [#57554](https://github.com/grafana/grafana/pull/57554), [@gtk-grafana](https://github.com/gtk-grafana)
- **Prometheus:** Provide label values match parameter API when supported prometheus instance is configured. [#57553](https://github.com/grafana/grafana/pull/57553), [@gtk-grafana](https://github.com/gtk-grafana)
- **Security:** Upgrade x/text to version unaffected by CVE-2022-32149. [#57797](https://github.com/grafana/grafana/pull/57797), [@yong-jie-gong](https://github.com/yong-jie-gong)
### Bug fixes
- **Access control:** Fix a bug with argument order for data source managed permission updates. (Enterprise)
- **Auth:** Fix GF_AUTH_JWT_URL_LOGIN env variable doesn't work. [#57689](https://github.com/grafana/grafana/pull/57689), [@Jguer](https://github.com/Jguer)
- **Live:** Explicitly reply with http 200. [#57428](https://github.com/grafana/grafana/pull/57428), [@sh0rez](https://github.com/sh0rez)
- **Prometheus:** Fix builder operation mode changing multiselect to single select behaviour. [#57780](https://github.com/grafana/grafana/pull/57780), [@itsmylife](https://github.com/itsmylife)
- **Prometheus:** Fix builder operation mode changing multiselect to single select behaviour. [#57493](https://github.com/grafana/grafana/pull/57493), [@yinjialu](https://github.com/yinjialu)
- **Security:** Fix vulnerabilities in webpack loader-utils. [#57533](https://github.com/grafana/grafana/pull/57533), [@jackw](https://github.com/jackw)
<!-- 9.2.3 END -->
<!-- 9.2.2 START -->
# 9.2.2 (2022-10-25)
### Features and enhancements
- **Alerting:** Add support for wecom apiapp. [#55991](https://github.com/grafana/grafana/pull/55991), [@aimuz](https://github.com/aimuz)
- **Canvas:** Improve resource picker initialization. [#57319](https://github.com/grafana/grafana/pull/57319), [@nmarrs](https://github.com/nmarrs)
- **Canvas:** Improve text element readability. [#57371](https://github.com/grafana/grafana/pull/57371), [@adela-almasan](https://github.com/adela-almasan)
- **CloudWatch:** Make sure adoption tracking is done on valid, migrated queries. [#56872](https://github.com/grafana/grafana/pull/56872), [@sunker](https://github.com/sunker)
- **Dashboard:** Alerts user to incorrect tag format for JSON import. [#54657](https://github.com/grafana/grafana/pull/54657), [@iamelDuderino](https://github.com/iamelDuderino)
- **MSSQL:** Support tables from all schemas. [#53099](https://github.com/grafana/grafana/pull/53099), [@zoltanbedi](https://github.com/zoltanbedi)
- **Opentsdb:** Allow template variables for filter keys. [#57226](https://github.com/grafana/grafana/pull/57226), [@bohandley](https://github.com/bohandley)
- **Prometheus:** Provide label values match parameter API when supported prometheus instance is configured. [#56510](https://github.com/grafana/grafana/pull/56510), [@gtk-grafana](https://github.com/gtk-grafana)
- **QueryEditor:** Revert components from grafana-ui. [#57436](https://github.com/grafana/grafana/pull/57436), [@zoltanbedi](https://github.com/zoltanbedi)
- **TeamSync:** Allow team sync when external organization mapping returns no organization role. (Enterprise)
### Bug fixes
- **Browse:** Fix General folder not showing in FolderPicker. [#57156](https://github.com/grafana/grafana/pull/57156), [@eledobleefe](https://github.com/eledobleefe)
- **Elasticsearch:** Fix calculation of trimEdges in alert mode. [#56148](https://github.com/grafana/grafana/pull/56148), [@jorgelbg](https://github.com/jorgelbg)
- **Elasticsearch:** Fix trimEdges delete logic in alert mode. [#56985](https://github.com/grafana/grafana/pull/56985), [@gabor](https://github.com/gabor)
- **GoogleOAuth:** Unlock User Admin UI. [#57350](https://github.com/grafana/grafana/pull/57350), [@gamab](https://github.com/gamab)
- **LogContext:** Fix wrong color of `show context` icon in light theme. [#57427](https://github.com/grafana/grafana/pull/57427), [@svennergr](https://github.com/svennergr)
- **Loki:** Fix adding of adhoc filters to stream selector when query with empty stream selector. [#57280](https://github.com/grafana/grafana/pull/57280), [@ivanahuckova](https://github.com/ivanahuckova)
- **Loki:** Fix double stringified log-lines when copied via Copy button. [#57243](https://github.com/grafana/grafana/pull/57243), [@svennergr](https://github.com/svennergr)
- **Loki:** Fix explain section about $\_\_interval variable. [#57188](https://github.com/grafana/grafana/pull/57188), [@ivanahuckova](https://github.com/ivanahuckova)
- **Loki:** Remove already selected options from next label filter options in builder. [#57187](https://github.com/grafana/grafana/pull/57187), [@ivanahuckova](https://github.com/ivanahuckova)
- **NodeGraph:** Fix rendering issues when values of arc are over 1. [#57460](https://github.com/grafana/grafana/pull/57460), [@aocenas](https://github.com/aocenas)
- **PublicDashboards:** Fix hidden queries execution. [#57194](https://github.com/grafana/grafana/pull/57194), [@juanicabanas](https://github.com/juanicabanas)
- **PublicDashboards:** Fix hidden queries execution. [#57004](https://github.com/grafana/grafana/pull/57004), [@juanicabanas](https://github.com/juanicabanas)
- **Tempo:** Fix Node Graph visualization type in dashboard. [#56931](https://github.com/grafana/grafana/pull/56931), [@CrypticSignal](https://github.com/CrypticSignal)
- **TimeSeries:** Fix stacking when first value is negative zero. [#57257](https://github.com/grafana/grafana/pull/57257), [@zoltanbedi](https://github.com/zoltanbedi)
- **TimeseriesPanel:** Fix variables in data links. [#56729](https://github.com/grafana/grafana/pull/56729), [@mdvictor](https://github.com/mdvictor)
- **User:** Fix externalUserId not being populated. [#57341](https://github.com/grafana/grafana/pull/57341), [@joshhunt](https://github.com/joshhunt)
### Breaking changes
We added some components a bit too early to @grafana/ui in 9.2 so we are moving them back to @grafana/experimental. If you used any of these components
- AccessoryButton
- EditorFieldGroup
- EditorHeader
- EditorField
- EditorRow
- EditorList
- EditorRows
- EditorSwitch
- FlexItem
- Stack
- InlineSelect
- InputGroup
- Space
Please use them from grafana/experimental from now on. Issue [#57436](https://github.com/grafana/grafana/issues/57436)
<!-- 9.2.2 END -->
<!-- 9.2.1 START -->
# 9.2.1 (2022-10-18)

View File

@@ -20,7 +20,7 @@ COPY emails emails
ENV NODE_ENV production
RUN yarn build
FROM golang:1.19.2-alpine3.15 as go-builder
FROM golang:1.19.3-alpine3.15 as go-builder
RUN apk add --no-cache gcc g++ make
@@ -57,8 +57,6 @@ ENV PATH="/usr/share/grafana/bin:$PATH" \
WORKDIR $GF_PATHS_HOME
RUN apk add --no-cache ca-certificates bash tzdata musl-utils
RUN apk add --no-cache openssl ncurses-libs ncurses-terminfo-base --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
RUN apk upgrade ncurses-libs ncurses-terminfo-base --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
RUN apk info -vv | sort
COPY conf ./conf

View File

@@ -21,7 +21,7 @@ COPY emails emails
ENV NODE_ENV production
RUN yarn build
FROM golang:1.19.2 AS go-builder
FROM golang:1.19.3 AS go-builder
WORKDIR /src/grafana

View File

@@ -210,10 +210,10 @@ check_for_updates = true
check_for_plugin_updates = true
# Google Analytics universal tracking code, only enabled if you specify an id here
google_analytics_ua_id =
google_analytics_ua_id =
# Google Analytics 4 tracking code, only enabled if you specify an id here
google_analytics_4_id =
google_analytics_4_id =
# Google Tag Manager ID, only enabled if you specify an id here
google_tag_manager_id =
@@ -626,6 +626,7 @@ key_file =
role_attribute_path =
role_attribute_strict = false
auto_sign_up = false
url_login = false
allow_assign_grafana_admin = false
#################################### Auth LDAP ###########################

View File

@@ -54,6 +54,8 @@ datasources:
jsonData:
manageAlerts: true
alertmanagerUid: gdev-alertmanager
prometheusType: Prometheus #Cortex | Mimir | Prometheus | Thanos
prometheusVersion: 2.40.0
- name: gdev-slow-prometheus
type: prometheus

View File

@@ -5,6 +5,7 @@ aliases:
- /docs/grafana/latest/enterprise/datasource_permissions/
- /docs/grafana/latest/permissions/datasource_permissions/
- /docs/grafana/latest/administration/data-source-management/
- /docs/grafana/latest/enterprise/query-caching/
title: Data source management
description: Data source management information for Grafana administrators
weight: 100
@@ -46,7 +47,7 @@ To add a data source:
Data source permissions allow you to restrict access for users to query a data source. For each data source there is a permission page that allows you to enable permissions and restrict query permissions to specific **Users** and **Teams**.
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud).
### Enable data source permissions
@@ -98,3 +99,86 @@ Note that _all_ existing permissions created for the data source will be deleted
1. On the Permissions tab, click **Disable Permissions**.
<div class="clearfix"></div>
## Query caching
When query caching is enabled, Grafana temporarily stores the results of data source queries. When you or another user submit the exact same query again, the results will come back from the cache instead of from the data source (like Splunk or ServiceNow) itself.
Query caching works for all backend data sources. You can enable the cache globally and configure the cache duration (also called Time to Live, or TTL).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
The following cache backends are available: in-memory, Redis, and Memcached.
> **Note:** Storing cached queries in-memory can increase Grafana's memory footprint. In production environments, a Redis or Memcached backend is highly recommended.
When a panel queries a cached data source, the time until this query fetches fresh data is determined by the panel's **interval.** This means that wider panels and dashboards with shorter time ranges fetch new data more frequently than narrower panels and dashboards with longer time ranges.
Interval is visible in a panel's [query options]({{< relref "../../panels-visualizations/query-transform-data/" >}}). It is calculated like this: `(max data points) / time range`. Max data points are calculated based on the width of the panel. For example, a full-width panel on a dashboard with a time range of `last 7 days` will retrieve fresh data every 10 minutes. In this example, cached data for this panel will be served for up to 10 minutes before Grafana queries the data source again and returns new data.
You can make a panel retrieve fresh data more frequently by increasing the **Max data points** setting in the panel's [query options]({{< relref "../../panels-visualizations/query-transform-data/" >}}).
### Query caching benefits
- Faster dashboard load times, especially for popular dashboards.
- Reduced API costs.
- Reduced likelihood that APIs will rate-limit or throttle requests.
### Data sources that work with query caching
Query caching works for all [Enterprise data sources](https://grafana.com/grafana/plugins/?type=datasource&enterprise=1) as well as the following [built-in data sources]({{< relref "../../datasources/" >}}):
- CloudWatch Metrics
- Google Cloud Monitoring
- InfluxDB
- Microsoft SQL Server
- MySQL
- Postgres
- Tempo
Some data sources, such as Elasticsearch, Prometheus, and Loki, cache queries themselves, so Grafana query caching does not improve performance.
Query caching also works for all data sources that include a backend. More specifically, caching works with data sources that extend the `DataSourceWithBackend` class in the plugins SDK.
To tell if a data source works with query caching, follow the instructions below to **Enable and Configure query caching**. If caching is enabled in Grafana but the Caching tab is not visible for the given data source, then query caching is not available for that data source.
### Enable and configure query caching
You must be an Org admin or Grafana admin to enable query caching for a data source. For more information on Grafana roles and permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/" >}}).
By default, data source queries are not cached. To enable query caching for a single data source:
1. On the side menu, click Configuration > Data Sources.
1. In the data source list, click the data source that you want to turn on caching for.
1. Open the Cache tab.
1. Press the Enable button.
1. (Optional) Choose custom TTLs for the data source's queries and resources caching. If you skip this step, then Grafana uses the default TTL.
> **Note:** If query caching is enabled and the Cache tab is not visible in a data source's settings, then query caching is not available for that data source.
To configure global settings for query caching, refer to the [Query caching section of Enterprise Configuration]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}).
### Disable query caching
To disable query caching for a single data source:
1. On the side menu, click Configuration > Data Sources.
1. In the data source list, click the data source that you want to turn off caching for.
1. In the Cache tab, click Disable.
To disable query caching for an entire Grafana instance, set the `enabled` flag to `false` in the [Query caching section of Enterprise Configuration]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}). You will no longer see the Cache tab on any data sources, and no data source queries will be cached.
### Clear cache
If you experience performance issues or repeated queries become slower to execute, consider clearing your cache.
> **Note:** This action impacts all cache-enabled data sources. If you are using Memcached, the system clears all data from the Memcached instance.
1. Sign in to Grafana and click **Settings > Data Sources**.
1. Select a data source.
1. Click the **Cache** tab.
1. Click **Clear cache**.
### Sending a request without cache
If a data source query request contains an `X-Cache-Skip` header, then Grafana skips the caching middleware, and does not search the cache for a response. This can be particularly useful when debugging data source queries using cURL.

View File

@@ -20,7 +20,7 @@ weight: 500
# Grafana Enterprise license
When you become a Grafana Enterprise customer, you gain access to Grafana's premium observability features, including enterprise data source plugins, reporting, and role-based access control. In order to use these [enhanced features of Grafana Enterprise]({{< relref "../../enterprise/" >}}), you must purchase and activate a Grafana Enterprise license.
When you become a Grafana Enterprise customer, you gain access to Grafana's premium observability features, including enterprise data source plugins, reporting, and role-based access control. In order to use these [enhanced features of Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise" >}}), you must purchase and activate a Grafana Enterprise license.
To purchase a license directly from Grafana Labs, [Contact a Grafana Labs representative](https://grafana.com/contact?about=grafana-enterprise). To activate an Enterprise license purchased from Grafana Labs, refer to [Activate an Enterprise license]({{< ref "#activate-an-enterprise-license" >}}).

View File

@@ -157,7 +157,7 @@ Since not all datasources have the same configuration settings we only have the
| httpMethod | string | Prometheus | HTTP Method. 'GET', 'POST', defaults to POST |
| customQueryParameters | string | Prometheus | Query parameters to add, as a URL-encoded string. |
| manageAlerts | boolean | Prometheus and Loki | Manage alerts via Alerting UI |
| esVersion | string | Elasticsearch | Elasticsearch version (E.g. `7.0.0`, `7.6.1`) |
| esVersion | string | Elasticsearch | Elasticsearch version (e.g. `7.0.0`, `7.6.1`) |
| timeField | string | Elasticsearch | Which field that should be used as timestamp |
| interval | string | Elasticsearch | Index date time format. nil(No Pattern), 'Hourly', 'Daily', 'Weekly', 'Monthly' or 'Yearly' |
| logMessageField | string | Elasticsearch | Which field should be used as the log message |
@@ -189,6 +189,8 @@ Since not all datasources have the same configuration settings we only have the
| maxIdleConns | number | MySQL, PostgreSQL and MSSQL | Maximum number of connections in the idle connection pool (Grafana v5.4+) |
| connMaxLifetime | number | MySQL, PostgreSQL and MSSQL | Maximum amount of time in seconds a connection may be reused (Grafana v5.4+) |
| keepCookies | array | _HTTP\*_ | Cookies that needs to be passed along while communicating with datasources |
| prometheusVersion | string | Prometheus | The version of the Prometheus datasource (e.g. `2.37.0`, `2.24.0`) |
| prometheusType | string | Prometheus | The type of the Prometheus datasources (i.e. `Prometheus`, `Cortex`, `Thanos`, or `Mimir`) |
#### Secure Json Data

View File

@@ -1,6 +1,7 @@
---
aliases:
- /docs/grafana/latest/enterprise/recorded-queries/
- /docs/grafana/latest/administration/recorded-queries/
description: Grafana Enterprise recorded queries
keywords:
- grafana
@@ -17,7 +18,7 @@ Recorded queries allow you to see trends over time by taking a snapshot of a dat
For our plugins that do not return time series, it might be useful to plot historical data. For example, you might want to query ServiceNow to see a history of request response times but it can only return current point-in-time metrics.
> **Note:** Available in [Grafana Enterprise]({{< relref "../enterprise/" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
## How recorded queries work

View File

@@ -147,7 +147,7 @@ For details on managing teams, see [Team management]({{< relref "../team-managem
While Grafana OSS includes a robust set of permissions and settings that you can use to manage user access to server and organization resources, you might find that you require additional capabilities.
[Grafana Enterprise]({{< relref "../../enterprise/">}}) provides the following permissions-related features:
[Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise">}}) provides the following permissions-related features:
- Data source permissions
- Role-based access control (RBAC)

View File

@@ -90,7 +90,7 @@ Assign fixed roles when the basic roles do not meet your permission requirements
- [Provisioning]({{< relref "../../provisioning/" >}})
- [Reports]({{< relref "../../../dashboards/create-reports/" >}})
- [Roles]({{< relref "../../" >}})
- [Settings]({{< relref "../../../enterprise/settings-updates/" >}})
- [Settings]({{< relref "../../../setup-grafana/configure-grafana/settings-updates-at-runtime" >}})
- [Service accounts]({{< relref "../../service-accounts/" >}})
- [Teams]({{< relref "../../team-management/" >}})
- [Users]({{< relref "../../user-management/" >}})

View File

@@ -116,7 +116,7 @@ The following list contains role-based access control actions.
| `serviceaccounts.permissions:write` | `serviceaccounts:*` | Update Grafana service account permissions to control who can do what with the service account. |
| `serviceaccounts.permissions:read` | `serviceaccounts:*` | Read Grafana service account permissions to see who can do what with the service account. |
| `settings:read` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Read the [Grafana configuration settings]({{< relref "../../../../setup-grafana/configure-grafana/" >}}) |
| `settings:write` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Update any Grafana configuration settings that can be [updated at runtime]({{< relref "../../../../enterprise/settings-updates/" >}}). |
| `settings:write` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Update any Grafana configuration settings that can be [updated at runtime]({{< relref "../../../../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}). |
| `status:accesscontrol` | `services:accesscontrol` | Get access-control enabled status. |
| `teams.permissions:read` | `teams:*`<br>`teams:id:*` | Read members and External Group Synchronization setup for teams. |
| `teams.permissions:write` | `teams:*`<br>`teams:id:*` | Add, remove and update members and manage External Group Synchronization setup for teams. |

View File

@@ -2,14 +2,15 @@
aliases:
- /docs/grafana/latest/enterprise/access-control/rbac-provisioning/
- /docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-provisioning/
description: Learn about RBAC provisioning and view an example YAML provisioning file
- /docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-grafana-provisioning
description: Learn about RBAC Grafana provisioning and view an example YAML provisioning file
that configures Grafana role assignments.
menuTitle: RBAC provisioning
title: Grafana RBAC provisioning
menuTitle: Provisioning RBAC with Grafana
title: Provisioning RBAC with Grafana
weight: 60
---
# Grafana RBAC provisioning
# Provisioning RBAC with Grafana
> **Note:** Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced]({{< ref "/docs/grafana-cloud" >}}).
@@ -117,3 +118,9 @@ teams:
# <string> state of the assignment. Defaults to 'present'. If 'absent', the assignment will be revoked.
state: absent
```
## Useful Links
[Provisioning RBAC setup with Terraform]({{< relref "./rbac-terraform-provisioning">}})
[Grafana provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/)

View File

@@ -0,0 +1,151 @@
---
aliases:
- /docs/grafana/latest/enterprise/access-control/rbac-provisioning/rbac-terraform-provisioning
description: Learn about RBAC Terraform provisioning and view an example of provisioning configuration
for Grafana roles and role assignments.
menuTitle: Provisioning RBAC with Terraform
title: Provisioning RBAC with Terraform
weight: 60
---
# Provisioning RBAC with Terraform
> **Note:** Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced]({{< ref "/docs/grafana-cloud" >}}).
You can create, change or remove [Custom roles](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/role) and create or remove [basic and custom role assignments](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/role_assignment), by using [Terraform's Grafana provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs).
## Before you begin
- Ensure you have the grafana/grafana [Terraform provider](https://registry.terraform.io/providers/grafana/grafana/) 1.29.0 or higher.
- Ensure you are using Grafana 9.2 or higher.
## Create a Service Account Token for provisioning
We recommend using service account tokens for provisioning. [Service accounts](https://grafana.com/docs/grafana/latest/administration/service-accounts/) support fine grained permissions, which allows you to easily authenticate and use the minimum set of permissions needed to provision your RBAC infrastructure.
To create a service account token for provisioning, complete the following steps.
1. [Create a new service account](https://grafana.com/docs/grafana/latest/administration/service-accounts/#create-a-service-account-in-grafana) for your CI pipeline.
1. [Assign permissions to service account](https://grafana.com/docs/grafana/latest/administration/service-accounts/#assign-roles-to-a-service-account-in-grafana):
1. You will need roles “Role reader”, "Role writer" and roles including any permissions that will be provisioned. For example, to create or assign a role that allows creating users, a service account needs permissions to create users.
1. Alternatively, you can assign "Admin" basic role to the service account.
1. [Create a new service account token](https://grafana.com/docs/grafana/latest/administration/service-accounts/#to-add-a-token-to-a-service-account) for use in Terraform.
Alternatively, you can use basic authentication. To view all the supported authentication formats, see [here](https://registry.terraform.io/providers/grafana/grafana/latest/docs#authentication).
## Configure the Terraform provider
RBAC support is included as part of the [Grafana Terraform provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs).
The following is an example you can use to configure the Terraform provider.
```terraform
terraform {
required_providers {
grafana = {
source = "grafana/grafana"
version = ">= 1.29.0"
}
}
}
provider "grafana" {
url = <YOUR_GRAFANA_URL>
auth = <YOUR_GRAFANA_SERVICE_ACCOUNT_TOKEN>
}
```
## Provision custom roles
The following example shows how to provision a custom role with some permissions.
1. Copy this code block into a .tf file on your local machine.
```terraform
resource "grafana_role" "my_new_role" {
name = "my_new_role"
description = "My test role"
version = 1
uid = "newroleuid"
global = true
permissions {
action = "org.users:add"
scope = "users:*"
}
permissions {
action = "org.users:write"
scope = "users:*"
}
permissions {
action = "org.users:read"
scope = "users:*"
}
permissions {
action = "teams:create"
}
permissions {
action = "teams:read"
scope = "teams:*"
}
permissions {
action = "teams:write"
scope = "teams:*"
}
}
```
2. Run the command `terraform apply`.
3. Go to Grafana's UI and check that the new role appears in the role picker:
![Role Picker](/static/img/docs/enterprise/tf_custom_role.png)
## Provision role assignments
The following example shows how to provision role assignments.
In this example a team, user and service account are provisioned, and the custom role from the previous example is assigned to them.
1. Extend the configuration file from the [previous example]({{##}}) with the following:
```terraform
resource "grafana_team" "test_team" {
name = "terraform_test_team"
}
resource "grafana_user" "test_user" {
email = "terraform_user@test.com"
login = "terraform_test_user"
password = <TEST_PASSWORD>
}
resource "grafana_service_account" "test_sa" {
name = "terraform_test_sa"
role = "Viewer"
}
resource "grafana_role_assignment" "my_new_role_assignment" {
role_uid = grafana_role.my_new_role.uid
users = [grafana_user.test_user.id]
teams = [grafana_team.test_team.id]
service_accounts = [grafana_service_account.test_sa.id]
}
```
1. Substitute `<TEST_PASSWORD>` with a test password for your test user.
1. Run the command `terraform apply`.
1. Go to Grafana's UI and check that a user, team and service account have been created, and that the role has been assigned to them:
![User Role Assignment](/static/img/docs/enterprise/tf_user_role_assignment.png)
![Team Role Assignment](/static/img/docs/enterprise/tf_team_role_assignment.png)
![Service Account Role Assignment](/static/img/docs/enterprise/tf_service_account_role_assignment.png)
Note that instead of using a provisioned role, you can also look up the `uid` of an already existing fixed or custom role and use that instead.
You can use the [API endpoint for listing roles](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/#create-and-manage-custom-roles) to look up role `uid`s.
Similarly, you can look up and use `id`s of users, teams and service accounts that have not been provisioned to assign roles to them.
## Useful Links
[RBAC setup with Grafana provisioning]({{< relref "./rbac-grafana-provisioning">}})
[Grafana Cloud Terraform provisioning](https://grafana.com/docs/grafana-cloud/infrastructure-as-code/terraform/)

View File

@@ -27,7 +27,7 @@ A common use case for creating a service account is to perform operations on aut
- Set up an external SAML authentication provider
- Interact with Grafana without signing in as a user
In [Grafana Enterprise]({{< relref "../../enterprise/" >}}), you can also use service accounts in combination with [role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}) to grant very specific permissions to applications that interact with Grafana.
In [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}), you can also use service accounts in combination with [role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}) to grant very specific permissions to applications that interact with Grafana.
> **Note:** Service accounts can only act in the organization they are created for. If you have the same task that is needed for multiple organizations, we recommend creating service accounts in each organization.
@@ -106,7 +106,7 @@ You can create a service account token using the Grafana UI or via the API. For
You can assign roles to a Grafana service account to control access for the associated service account tokens.
You can assign roles to a service account using the Grafana UI or via the API. For more information about assigning a role to a service account via the API, refer to [Update service account using the HTTP API]({{< relref "../../developers/http_api/serviceaccount/#update-service-account" >}}).
In [Grafana Enterprise]({{< relref "../../enterprise/" >}}), you can also [assign RBAC roles]({{< relref "../roles-and-permissions/access-control/assign-rbac-roles" >}}) to grant very specific permissions to applications that interact with Grafana.
In [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}), you can also [assign RBAC roles]({{< relref "../roles-and-permissions/access-control/assign-rbac-roles" >}}) to grant very specific permissions to applications that interact with Grafana.
### Before you begin

View File

@@ -31,7 +31,6 @@ The following table lists the contact point types supported by Grafana.
| [Pagerduty](https://www.pagerduty.com/) | `pagerduty` | Supported | Supported |
| [Prometheus Alertmanager](https://prometheus.io) | `prometheus-alertmanager` | Supported | N/A |
| [Pushover](https://pushover.net/) | `pushover` | Supported | Supported |
| [Sensu](https://sensu.io/) | `sensu` | Supported | N/A |
| [Sensu Go](https://docs.sensu.io/sensu-go/) | `sensugo` | Supported | N/A |
| [Slack](https://slack.com/) | `slack` | Supported | Supported |
| [Telegram](https://telegram.org/) | `telegram` | Supported | N/A |

View File

@@ -76,7 +76,7 @@ Only organization administrators can create reports by default. You can customiz
### Choose template variables
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 7.5 and later behind the `reportVariables` feature flag, Grafana Enterprise version 8.0 and later without a feature flag, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.5 and later behind the `reportVariables` feature flag, Grafana Enterprise version 8.0 and later without a feature flag, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can configure report-specific template variables for the dashboard on the report page. The variables that you select will override the variables from the dashboard, and they are used when rendering a PDF file of the report. For detailed information about using template variables, refer to the [Templates and variables]({{< relref "../variables/" >}}) section.
@@ -84,7 +84,7 @@ You can configure report-specific template variables for the dashboard on the re
### Render a report with panels or rows set to repeat by a variable
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can include dynamic dashboards with panels or rows, set to repeat by a variable, into reports. For detailed information about setting up repeating panels or rows in dashboards, refer to [Repeat panels or rows]({{< relref "../../panels-visualizations/configure-panel-options/#configure-repeating-rows-or-panels" >}}).
@@ -99,7 +99,7 @@ You can include dynamic dashboards with panels or rows, set to repeat by a varia
### Report time range
> **Note:** You can set custom report time ranges in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) 7.2+ and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** You can set custom report time ranges in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) 7.2+ and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
By default, reports use the saved time range of the dashboard. You can change the time range of the report by:
@@ -123,7 +123,7 @@ If the time zone is set differently between your Grafana server and its remote i
### CSV export
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) 8+ with the [Grafana image renderer plugin](https://grafana.com/grafana/plugins/grafana-image-renderer) v3.0+, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) 8+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can attach a CSV file to the report email for each table panel on the selected dashboard, along with the PDF report. By default, CSVs larger than 10Mb are not sent which keeps email servers from rejecting the email. You can increase or decrease this limit in the [reporting configuration]({{< relref "#rendering-configuration" >}}).
@@ -135,7 +135,7 @@ A background job runs every 10 minutes and removes temporary CSV files. You can
### Scheduling
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
> The scheduler was significantly changed in Grafana Enterprise version 8.1.
Scheduled reports can be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**, for example to send the report via the API.
@@ -158,7 +158,7 @@ When you schedule a report with a monthly frequency, and set the start date betw
#### Send a test email
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 7.0 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
1. In the report, click **Send test email**.
1. In the **Email** field, enter the email address or addresses that you want to test, separated by a semicolon.
@@ -171,19 +171,19 @@ The last saved version of the report will be sent to selected emails. You can us
### Pause a report
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 8.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can pause sending reports from the report list view by clicking the pause icon. The report will not be sent according to its schedule until it is resumed by clicking the resume button on the report row.
### Add multiple dashboards to a report
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 9.0 and later, and [Grafana Cloud Pro and Advanced]({{< relref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 9.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can add more than one dashboard to a report. Additional dashboards will be rendered as new pages in the same PDF file, or additional images if you chose to embed images in your report email. You cannot add the same dashboard to a report multiple times.
### Embed a dashboard as an image into a report
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 9.0 and later, and [Grafana Cloud Pro and Advanced]({{< relref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 9.0 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can send a report email with an image of the dashboard embedded in the email instead of attached as a PDF. In this case, the email recipients can see the dashboard at a glance instead of having to open the PDF.
@@ -238,7 +238,7 @@ font_italic = DejaVuSansCondensed-Oblique.ttf
## Report settings
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 7.2 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.2 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
You can configure organization-wide report settings in the **Settings** tab on the **Reporting** page. Settings are applied to all the reports for current organization.

View File

@@ -21,25 +21,27 @@ Grafana includes built-in support for Prometheus. This topic explains options, v
To access Prometheus settings, hover your mouse over the **Configuration** (gear) icon, then click **Data Sources**, and then click the Prometheus data source.
| Name | Description |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Name` | The data source name. This is how you refer to the data source in panels and queries. |
| `Default` | Default data source that is pre-selected for new panels. |
| `Url` | The URL of your Prometheus server, for example, `http://prometheus.example.org:9090`. |
| `Access` | Only Server access mode is functional. If Server mode is already selected this option is hidden. Otherwise change to Server mode to prevent errors. |
| `Basic Auth` | Enable basic authentication to the Prometheus data source. |
| `User` | User name for basic authentication. |
| `Password` | Password for basic authentication. |
| `Scrape interval` | Set this to the typical scrape and evaluation interval configured in Prometheus. Defaults to 15s. |
| `HTTP method` | Use either POST or GET HTTP method to query your data source. POST is the recommended and pre-selected method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network. |
| `Disable metrics lookup` | Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances. |
| `Custom Query Parameters` | Add custom parameters to the Prometheus query URL. For example `timeout`, `partial_response`, `dedup`, or `max_source_resolution`. Multiple parameters should be concatenated together with an '&amp;'. |
| **Exemplars configuration** | |
| `Internal link` | Enable this option is you have an internal link. When you enable this option, you will see a data source selector. Select the backend tracing data store for your exemplar data. |
| `Data source` | You will see this option only if you enable `Internal link` option. Select the backend tracing data store for your exemplar data. |
| `URL` | You will see this option only if the `Internal link` option is disabled. Enter the full URL of the external link. You can interpolate the value from the field with `${__value.raw }` macro. |
| `URL Label` | (Optional) add a custom display label to override the value of the `Label name` field. |
| `Label name` | Add a name for the exemplar traceID property. |
| Name | Description |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Name` | The data source name. This is how you refer to the data source in panels and queries. |
| `Default` | Default data source that is pre-selected for new panels. |
| `Url` | The URL of your Prometheus server, for example, `http://prometheus.example.org:9090`. |
| `Access` | Only Server access mode is functional. If Server mode is already selected this option is hidden. Otherwise change to Server mode to prevent errors. |
| `Basic Auth` | Enable basic authentication to the Prometheus data source. |
| `User` | User name for basic authentication. |
| `Password` | Password for basic authentication. |
| `Scrape interval` | Set this to the typical scrape and evaluation interval configured in Prometheus. Defaults to 15s. |
| `HTTP method` | Use either POST or GET HTTP method to query your data source. POST is the recommended and pre-selected method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network. |
| `Type` | The type of your Prometheus server, i.e `Prometheus`, `Cortex`, `Thanos` or `Mimir`. When this value is selected in the configuration UI, the Prometheus version field attempts to detect the version automatically using the Prometheus [buildinfo](https://semver.org/) API. Some Prometheus types do not support this API, and you will need to manually populate the version in those cases (e.g. Cortex). |
| `Version` | The version of your Prometheus server, note that this field is not visible until the Prometheus type is selected. |
| `Disable metrics lookup` | Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances. |
| `Custom Query Parameters` | Add custom parameters to the Prometheus query URL. For example `timeout`, `partial_response`, `dedup`, or `max_source_resolution`. Multiple parameters should be concatenated together with an '&amp;'. |
| **Exemplars configuration** | |
| `Internal link` | Enable this option is you have an internal link. When you enable this option, you will see a data source selector. Select the backend tracing data store for your exemplar data. |
| `Data source` | You will see this option only if you enable `Internal link` option. Select the backend tracing data store for your exemplar data. |
| `URL` | You will see this option only if the `Internal link` option is disabled. Enter the full URL of the external link. You can interpolate the value from the field with `${__value.raw }` macro. |
| `URL Label` | (Optional) add a custom display label to override the value of the `Label name` field. |
| `Label name` | Add a name for the exemplar traceID property. |
## Prometheus query editor
@@ -176,13 +178,13 @@ types of template variables.
Variable of the type _Query_ allows you to query Prometheus for a list of metrics, labels or label values. The Prometheus data source plugin
provides the following functions you can use in the `Query` input field.
| Name | Description | Used API endpoints |
| ----------------------------- | ----------------------------------------------------------------------- | --------------------------------- |
| `label_names()` | Returns a list of label names. | /api/v1/labels |
| `label_values(label)` | Returns a list of label values for the `label` in every metric. | /api/v1/label/`label`/values |
| `label_values(metric, label)` | Returns a list of label values for the `label` in the specified metric. | /api/v1/series |
| `metrics(metric)` | Returns a list of metrics matching the specified `metric` regex. | /api/v1/label/\_\_name\_\_/values |
| `query_result(query)` | Returns a list of Prometheus query result for the `query`. | /api/v1/query |
| Name | Description | Used API endpoints |
| ----------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `label_names()` | Returns a list of label names. | /api/v1/labels |
| `label_values(label)` | Returns a list of label values for the `label` in every metric. | /api/v1/label/`label`/values |
| `label_values(metric, label)` | Returns a list of label values for the `label` in the specified metric. | /api/v1/series or /api/v1/label/`label`/values, depending on prometheus type and version in datasource configuration |
| `metrics(metric)` | Returns a list of metrics matching the specified `metric` regex. | /api/v1/label/\_\_name\_\_/values |
| `query_result(query)` | Returns a list of Prometheus query result for the `query`. | /api/v1/query |
For details of what _metric names_, _label names_ and _label values_ are please refer to the [Prometheus documentation](http://prometheus.io/docs/concepts/data_model/#metric-names-and-labels).
@@ -282,6 +284,8 @@ datasources:
url: http://localhost:9090
jsonData:
httpMethod: POST
prometheusType: Prometheus
prometheusVersion: 2.37.0
exemplarTraceIdDestinations:
# Field with internal link pointing to data source in Grafana.
# datasourceUid value can be anything, but it should be unique across all defined data source uids.

View File

@@ -17,7 +17,7 @@ title: RBAC HTTP API
# RBAC API
> Role-based access control API is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
> Role-based access control API is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
The API can be used to create, update, delete, get, and list roles.

View File

@@ -28,10 +28,10 @@ Here's a cURL command that works for getting the home dashboard when you are run
curl http://admin:admin@localhost:3000/api/search
```
To pass a username and password with [HTTP basic authorization]({{< relref "/administration/roles-and-permissions/access-control/manage-rbac-roles/" >}}), encode them as base64.
To pass a username and password with [HTTP basic authorization]({{< relref "../../administration/roles-and-permissions/access-control/manage-rbac-roles/" >}}), encode them as base64.
You can't use authorization tokens in the request.
For example, to [list permissions associated with roles]({{< relref "/administration/roles-and-permissions/access-control/manage-rbac-roles/" >}}) given a username of `user` and password of `password`, use:
For example, to [list permissions associated with roles]({{< relref "../../administration/roles-and-permissions/access-control/manage-rbac-roles/" >}}) given a username of `user` and password of `password`, use:
```
curl --location --request GET '<grafana_url>/api/access-control/builtin-roles' --header 'Authorization: Basic dXNlcjpwYXNzd29yZAo='

View File

@@ -19,7 +19,7 @@ title: 'Datasource Permissions HTTP API'
# Data Source Permissions API
> The Data Source Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
> The Data Source Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.

View File

@@ -18,7 +18,7 @@ title: 'External Group Sync HTTP API'
# External Group Synchronization API
> External Group Synchronization is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
> External Group Synchronization is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.

View File

@@ -15,7 +15,7 @@ title: 'Licensing HTTP API'
# Enterprise License API
Licensing is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
Licensing is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.

View File

@@ -17,7 +17,7 @@ This API allows you to interact programmatically with the [Reporting]({{< relref
> The Reporting API is not stabilized yet, it is still in active development and may change without prior notice.
> Reporting is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
> Reporting is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}).
> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.

View File

@@ -1,97 +0,0 @@
---
aliases:
- /docs/grafana/latest/enterprise/query-caching/
description: Grafana Enterprise data source query caching
keywords:
- grafana
- plugins
- query
- caching
title: Query caching
weight: 300
---
# Query caching
When query caching is enabled, Grafana temporarily stores the results of data source queries. When you or another user submit the exact same query again, the results will come back from the cache instead of from the data source (like Splunk or ServiceNow) itself.
Query caching works for all backend data sources. You can enable the cache globally and configure the cache duration (also called Time to Live, or TTL).
> **Note:** Available in [Grafana Enterprise]({{< relref "../enterprise/" >}}) and [Grafana Cloud Pro and Advanced]({{< ref "/grafana-cloud" >}}).
The following cache backends are available: in-memory, Redis, and Memcached.
> **Note:** Storing cached queries in-memory can increase Grafana's memory footprint. In production environments, a Redis or Memcached backend is highly recommended.
When a panel queries a cached data source, the time until this query fetches fresh data is determined by the panel's **interval.** This means that wider panels and dashboards with shorter time ranges fetch new data more frequently than narrower panels and dashboards with longer time ranges.
Interval is visible in a panel's [query options]({{< relref "../panels-visualizations/query-transform-data/" >}}). It is calculated like this: `(max data points) / time range`. Max data points are calculated based on the width of the panel. For example, a full-width panel on a dashboard with a time range of `last 7 days` will retrieve fresh data every 10 minutes. In this example, cached data for this panel will be served for up to 10 minutes before Grafana queries the data source again and returns new data.
You can make a panel retrieve fresh data more frequently by increasing the **Max data points** setting in the panel's [query options]({{< relref "../panels-visualizations/query-transform-data/" >}}).
## Query caching benefits
- Faster dashboard load times, especially for popular dashboards.
- Reduced API costs.
- Reduced likelihood that APIs will rate-limit or throttle requests.
## Data sources that work with query caching
Query caching works for all [Enterprise data sources](https://grafana.com/grafana/plugins/?type=datasource&enterprise=1) as well as the following [built-in data sources]({{< relref "../datasources/" >}}):
- CloudWatch Metrics
- Google Cloud Monitoring
- InfluxDB
- Microsoft SQL Server
- MySQL
- Postgres
- Tempo
Some data sources, such as Elasticsearch, Prometheus, and Loki, cache queries themselves, so Grafana query caching does not improve performance.
Query caching also works for all data sources that include a backend. More specifically, caching works with data sources that extend the `DataSourceWithBackend` class in the plugins SDK.
To tell if a data source works with query caching, follow the instructions below to **Enable and Configure query caching**. If caching is enabled in Grafana but the Caching tab is not visible for the given data source, then query caching is not available for that data source.
## Enable and configure query caching
You must be an Org admin or Grafana admin to enable query caching for a data source. For more information on Grafana roles and permissions, refer to [About users and permissions]({{< relref "../administration/roles-and-permissions/" >}}).
By default, data source queries are not cached. To enable query caching for a single data source:
1. On the side menu, click Configuration > Data Sources.
1. In the data source list, click the data source that you want to turn on caching for.
1. Open the Cache tab.
1. Press the Enable button.
1. (Optional) Choose custom TTLs for the data source's queries and resources caching. If you skip this step, then Grafana uses the default TTL.
> **Note:** If query caching is enabled and the Cache tab is not visible in a data source's settings, then query caching is not available for that data source.
To configure global settings for query caching, refer to the [Query caching section of Enterprise Configuration]({{< relref "../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}).
## Disable query caching
To disable query caching for a single data source:
1. On the side menu, click Configuration > Data Sources.
1. In the data source list, click the data source that you want to turn off caching for.
1. In the Cache tab, click Disable.
To disable query caching for an entire Grafana instance, set the `enabled` flag to `false` in the [Query caching section of Enterprise Configuration]({{< relref "../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}). You will no longer see the Cache tab on any data sources, and no data source queries will be cached.
## Clear cache
If you experience performance issues or repeated queries become slower to execute, consider clearing your cache.
> **Note:** This action impacts all cache-enabled data sources. If you are using Memcached, the system clears all data from the Memcached instance.
**To clear the cache**:
1. Sign in to Grafana and click **Settings > Data Sources**.
1. Select a data source.
1. Click the **Cache** tab.
1. Click **Clear cache**.
## Sending a request without cache
If a data source query request contains an `X-Cache-Skip` header, then Grafana skips the caching middleware, and does not search the cache for a response. This can be particularly useful when debugging data source queries using cURL.

View File

@@ -11,8 +11,6 @@ weight: 400
{{< docs/shared "influxdb/intro.md" >}}
> **Note:** You can also configure a [Grafana Cloud](https://grafana.com/docs/grafana-cloud/) instance to display system metrics without having to host Grafana yourself. Grafana offers a [free account with Grafana Cloud](https://grafana.com/signup/cloud/connect-account?pg=gsdocs) to help you get started.
{{< docs/shared "getting-started/first-step.md" >}}
#### Get InfluxDB

View File

@@ -13,8 +13,6 @@ weight: 300
Prometheus is an open source monitoring system for which Grafana provides out-of-the-box support. This topic walks you through the steps to create a series of dashboards in Grafana to display system metrics for a server monitored by Prometheus.
> **Note:** You can configure a [Grafana Cloud](https://grafana.com/docs/grafana-cloud/) instance to display system metrics without having to host Grafana yourself. A [free forever plan](https://grafana.com/signup/cloud/connect-account?pg=gsdocs) provides 10,000 active series for metrics.
{{< docs/shared "getting-started/first-step.md" >}}
#### Download Prometheus and node_exporter

View File

@@ -51,7 +51,7 @@ Discover hundreds of [dashboards](https://grafana.com/grafana/dashboards) and [p
Grafana supports different authentication methods, such as LDAP and OAuth, and allows you to map users to organizations. Refer to the [User authentication overview]({{< relref "../setup-grafana/configure-security/configure-authentication/" >}}) for more information.
In Grafana Enterprise, you can also map users to teams: If your company has its own authentication system, Grafana allows you to map the teams in your internal systems to teams in Grafana. That way, you can automatically give people access to the dashboards designated for their teams. Refer to [Grafana Enterprise]({{< relref "../enterprise/_index.md" >}}) for more information.
In Grafana Enterprise, you can also map users to teams: If your company has its own authentication system, Grafana allows you to map the teams in your internal systems to teams in Grafana. That way, you can automatically give people access to the dashboards designated for their teams. Refer to [Grafana Enterprise]({{< relref "./grafana-enterprise" >}}) for more information.
## Provisioning
@@ -61,7 +61,7 @@ For example, if you're spinning up a new Kubernetes cluster, you can also spin u
## Permissions
When organizations have one Grafana and multiple teams, they often want the ability to both keep things separate and share dashboards. You can create a team of users and then set permissions on [folders and dashboards]({{< relref "../administration/user-management/manage-dashboard-permissions/" >}}), and down to the [data source level]({{< relref "../administration/data-source-management#data-source-permissions" >}}) if you're using [Grafana Enterprise]({{< relref "../enterprise/" >}}).
When organizations have one Grafana and multiple teams, they often want the ability to both keep things separate and share dashboards. You can create a team of users and then set permissions on [folders and dashboards]({{< relref "../administration/user-management/manage-dashboard-permissions/" >}}), and down to the [data source level]({{< relref "../administration/data-source-management#data-source-permissions" >}}) if you're using [Grafana Enterprise]({{< relref "./grafana-enterprise" >}}).
## Other Grafana Labs OSS Projects

View File

@@ -17,7 +17,7 @@ To learn more about Grafana Enterprise, refer to [our product page](https://graf
## Enterprise features in Grafana Cloud
Many Grafana Enterprise features are also available in [Grafana Cloud]({{< ref "/docs/grafana-cloud" >}}) Pro and Advanced accounts. For details, refer to [the Grafana Cloud features table](https://grafana.com/pricing/#featuresTable) and [Enterprise features available to Grafana Cloud Pro and Advanced accounts]({{< ref "/docs/grafana-cloud/reference/enterprise-features" >}}).
Many Grafana Enterprise features are also available in [Grafana Cloud]({{< ref "/docs/grafana-cloud" >}}) Pro and Advanced accounts. For details, refer to [the Grafana Cloud features table](https://grafana.com/pricing/#featuresTable).
## Authentication
@@ -55,16 +55,16 @@ Grafana Enterprise adds the following features:
- [Role-based access control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) to control access with role-based permissions.
- [Data source permissions]({{< relref "../administration/data-source-management#data-source-permissions" >}}) to restrict query access to specific teams and users.
- [Data source query caching]({{< relref "../enterprise/query-caching.md" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting.
- [Data source query caching]({{< relref "../administration/data-source-management/#query-caching" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting.
- [Reporting]({{< relref "../dashboards/create-reports/" >}}) to generate a PDF report from any dashboard and set up a schedule to have it emailed to whomever you choose.
- [Export dashboard as PDF]({{< relref "../dashboards/share-dashboards-panels/#export-dashboard-as-pdf" >}})
- [Custom branding]({{< relref "../setup-grafana/configure-grafana/configure-custom-branding/" >}}) to customize Grafana from the brand and logo to the footer links.
- [Usage insights]({{< relref "../dashboards/assess-dashboard-usage/" >}}) to understand how your Grafana instance is used.
- [Recorded queries]({{< relref "../enterprise/recorded-queries" >}}) to see trends over time for your data sources.
- [Recorded queries]({{< relref "../administration/recorded-queries" >}}) to see trends over time for your data sources.
- [Vault integration]({{< relref "../setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-hashicorp-key-vault/" >}}) to manage your configuration or provisioning secrets with Vault.
- [Auditing]({{< relref "../setup-grafana/configure-security/audit-grafana/" >}}) tracks important changes to your Grafana instance to help you manage and mitigate suspicious activity and meet compliance requirements.
- [Request security]({{< relref "../setup-grafana/configure-security/configure-request-security/" >}}) makes it possible to restrict outgoing requests from the Grafana server.
- [Settings updates at runtime]({{< relref "../enterprise/settings-updates.md" >}}) allows you to update Grafana settings at runtime without requiring a restart.
- [Settings updates at runtime]({{< relref "../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}) allows you to update Grafana settings at runtime without requiring a restart.
## Enterprise data sources

View File

@@ -359,11 +359,9 @@ The result after applying the inner join transformation looks like the following
#### Outer join
An outer join includes all data from an inner join and rows where values do not match in every input.
An outer join includes all data from an inner join and rows where values do not match in every input. While the inner join joins Query A and Query B on the time field, the outer join includes all rows that dont match on the time field.
Use this transformation to combine the results from multiple queries (combining on a passed join field or the first time column) into one result, and drop rows where a successful join cannot occur - performing an inner join.
In the following example, two queries return table data. It is visualized as two tables before applying the inner join transformation.
In the following example, two queries return table data. It is visualized as two tables before applying the outer join transformation.
Query A:
@@ -381,10 +379,12 @@ Query B:
| 2020-07-07 11:24:20 | server 2 | 5 |
| 2020-07-07 11:04:20 | server 3 | 10 |
The result after applying the inner join transformation looks like the following:
The result after applying the outer join transformation looks like the following:
| Time | Job | Uptime | Server | Errors |
| ------------------- | ------- | --------- | -------- | ------ |
| 2020-07-07 11:04:20 | | | server 3 | 10 |
| 2020-07-07 11:14:20 | postgre | 345001233 | | |
| 2020-07-07 11:34:20 | node | 25260122 | server 1 | 15 |
| 2020-07-07 11:24:20 | postgre | 123001233 | server 2 | 5 |

View File

@@ -124,7 +124,7 @@ password = $__file{/etc/secrets/gf_sql_password}
The `vault` provider allows you to manage your secrets with [Hashicorp Vault](https://www.hashicorp.com/products/vault).
> Vault provider is only available in Grafana Enterprise v7.1+. For more information, refer to [Vault integration]({{< relref "../configure-security/configure-database-encryption/integrate-with-hashicorp-vault/" >}}) in [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
> Vault provider is only available in Grafana Enterprise v7.1+. For more information, refer to [Vault integration]({{< relref "../configure-security/configure-database-encryption/integrate-with-hashicorp-vault/" >}}) in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise" >}}).
<hr />
@@ -369,7 +369,7 @@ Defaults to `private`.
## [remote_cache]
Caches authentication details and session information in the configured database, Redis or Memcached. This setting does not configure [Query Caching in Grafana Enterprise]({{< relref "../../enterprise/query-caching/" >}}).
Caches authentication details and session information in the configured database, Redis or Memcached. This setting does not configure [Query Caching in Grafana Enterprise]({{< relref "../../administration/data-source-management/#query-caching" >}}).
### type
@@ -534,6 +534,10 @@ Default is `admin`.
The password of the default Grafana Admin. Set once on first-run. Default is `admin`.
# admin_email
The email of the default Grafana Admin, created on startup. Default is `admin@localhost`.
### secret_key
Used for signing some data source settings like secrets and passwords, the encryption format used is AES-256 in CFB mode. Cannot be changed without requiring an update
@@ -1951,7 +1955,7 @@ Change the listening port of the gRPC server. Default port is `0` and will autom
## [enterprise]
For more information about Grafana Enterprise, refer to [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
For more information about Grafana Enterprise, refer to [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise" >}}).
<hr>

View File

@@ -375,7 +375,7 @@ Setting 'enabled' to `true` allows users to configure query caching for data sou
This value is `true` by default.
> **Note:** This setting enables the caching feature, but it does not turn on query caching for any data source. To turn on query caching for a data source, update the setting on the data source configuration page. For more information, refer to the [query caching docs]({{< relref "../../enterprise/query-caching/#enable-and-configure-query-caching" >}}).
> **Note:** This setting enables the caching feature, but it does not turn on query caching for any data source. To turn on query caching for a data source, update the setting on the data source configuration page. For more information, refer to the [Query caching]({{< relref "../../../administration/data-source-management/#enable-and-configure-query-caching" >}}).
### ttl

View File

@@ -17,7 +17,7 @@ weight: 500
By updating settings at runtime, you can update Grafana settings without needing to restart the Grafana server.
Updates that happen at runtime are stored in the database and override
[settings from the other sources]({{< relref "../setup-grafana/configure-grafana/" >}})
[settings from the other sources]({{< relref "../../configure-grafana/" >}})
(arguments, environment variables, settings file, etc). Therefore, every time a specific setting key is removed at runtime,
the value used for that key is the inherited one from the other sources in the reverse order of precedence
(`arguments > environment variables > settings file`), being the application default the value used when no one provided
@@ -27,7 +27,7 @@ Currently, **it only supports updates on the `auth.saml` section.**
## Update settings via the API
You can update settings through the [Admin API]({{< relref "../developers/http_api/admin/#update-settings" >}}).
You can update settings through the [Admin API]({{< relref "../../../developers/http_api/admin/#update-settings" >}}).
When you submit a settings update via API, Grafana verifies if the given settings updates are allowed and valid. If they are, then Grafana stores the settings in the database and reloads
Grafana services with no need to restart the instance.
@@ -92,5 +92,5 @@ HTTP API, then the other instances are synchronized through the database and the
## Control access with role-based access control
If you have [role-based access control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) enabled, you can control who can read or update settings.
Refer to the [Admin API]({{< relref "../developers/http_api/admin/#update-settings" >}}) for more information.
If you have [role-based access control]({{< relref "../../../administration/roles-and-permissions/access-control/" >}}) enabled, you can control who can read or update settings.
Refer to the [Admin API]({{< relref "../../../developers/http_api/admin/#update-settings" >}}) for more information.

View File

@@ -16,7 +16,9 @@ weight: 800
Auditing allows you to track important changes to your Grafana instance. By default, audit logs are logged to file but the auditing feature also supports sending logs directly to Loki.
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 7.3 and later, and [Grafana Cloud Advanced]({{< ref "/docs/grafana-cloud" >}}).
Only API requests or UI actions that trigger an API request generate an audit log.
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.3 and later, and [Grafana Cloud Advanced](/docs/grafana-cloud).
## Audit logs

View File

@@ -50,19 +50,19 @@ You can re-encrypt secrets in order to:
- Move already existing secrets' encryption forward from legacy to envelope encryption.
- Re-encrypt secrets after a [data keys rotation](#rotate-data-keys).
To re-encrypt secrets, use the [Grafana CLI]({{< ref "/cli/" >}}) by running the `grafana-cli admin secrets-migration re-encrypt` command or the `/encryption/reencrypt-secrets` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#roll-back-secrets" >}}). It's safe to run more than once, more recommended under maintenance mode.
To re-encrypt secrets, use the [Grafana CLI]({{< ref "../../../cli" >}}) by running the `grafana-cli admin secrets-migration re-encrypt` command or the `/encryption/reencrypt-secrets` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#roll-back-secrets" >}}). It's safe to run more than once, more recommended under maintenance mode.
### Roll back secrets
You can roll back secrets encrypted with envelope encryption to legacy encryption. This might be necessary to downgrade to Grafana versions prior to v9.0 after an unsuccessful upgrade.
To roll back secrets, use the [Grafana CLI]({{< ref "/cli/" >}}) by running the `grafana-cli admin secrets-migration rollback` command or the `/encryption/rollback-secrets` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#re-encrypt-secrets" >}}). It's safe to run more than once, more recommended under maintenance mode.
To roll back secrets, use the [Grafana CLI]({{< ref "../../../cli" >}}) by running the `grafana-cli admin secrets-migration rollback` command or the `/encryption/rollback-secrets` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#re-encrypt-secrets" >}}). It's safe to run more than once, more recommended under maintenance mode.
### Re-encrypt data keys
You can re-encrypt data keys encrypted with a specific key encryption key (KEK). This allows you to either re-encrypt existing data keys with a new KEK version (see [KMS integration](#kms-integration) rotation) or to re-encrypt them with a completely different KEK.
To re-encrypt data keys, use the [Grafana CLI]({{< ref "/cli/" >}}) by running the `grafana-cli admin secrets-migration re-encrypt-data-keys` command or the `/encryption/reencrypt-data-keys` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#re-encrypt-data-encryption-keys" >}}). It's safe to run more than once, more recommended under maintenance mode.
To re-encrypt data keys, use the [Grafana CLI]({{< ref "../../../cli" >}}) by running the `grafana-cli admin secrets-migration re-encrypt-data-keys` command or the `/encryption/reencrypt-data-keys` endpoint of the Grafana [Admin API]({{< relref "../../../developers/http_api/admin/#re-encrypt-data-encryption-keys" >}}). It's safe to run more than once, more recommended under maintenance mode.
### Rotate data keys

View File

@@ -15,7 +15,7 @@ Request security allows you to limit requests from the Grafana server by targeti
This can be used to limit access to internal systems that the server Grafana runs on can access but that users of Grafana should not be able to access. This feature does not affect traffic from the Grafana users browser.
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) version 7.4 and later, and [Grafana Cloud Pro and Advanced]({{< ref "/docs/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) version 7.4 and later, and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
> **Note:** Although request security works with backend plugins, you can create a backend plugin that bypasses this security.

View File

@@ -14,7 +14,7 @@ weight: 1000
Team sync lets you set up synchronization between your auth providers teams and teams in Grafana. This enables LDAP, OAuth, or SAML users who are members of certain teams or groups to automatically be added or removed as members of certain teams in Grafana.
> **Note:** Available in [Grafana Enterprise]({{< relref "../../enterprise/" >}}) and [Grafana Cloud Advanced]({{< ref "/docs/grafana-cloud" >}}).
> **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced](/docs/grafana-cloud/).
Grafana keeps track of all synchronized users in teams, and you can see which users have been synchronized in the team members list, see `LDAP` label in screenshot.
This mechanism allows Grafana to remove an existing synchronized user from a team when its group membership changes. This mechanism also enables you to manually add a user as member of a team, and it will not be removed when the user signs in. This gives you flexibility to combine LDAP group memberships and Grafana team memberships.

View File

@@ -15,7 +15,7 @@ weight: 1000
# Set up image rendering
Grafana supports automatic rendering of panels as PNG images. This allows Grafana to automatically generate images of your panels to include in [alert notifications]({{< relref "../../alerting/notifications/" >}}), [PDF export]({{< relref "../../dashboards/create-reports/#export-dashboard-as-pdf" >}}), and [Reporting]({{< relref "../../dashboards/create-reports/" >}}). PDF Export and Reporting are available only in [Grafana Enterprise]({{< relref "../../enterprise/" >}}).
Grafana supports automatic rendering of panels as PNG images. This allows Grafana to automatically generate images of your panels to include in alert notifications, [PDF export]({{< relref "../../dashboards/create-reports/#export-dashboard-as-pdf" >}}), and [Reporting]({{< relref "../../dashboards/create-reports/" >}}). PDF Export and Reporting are available only in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise" >}}).
> **Note:** Image rendering of dashboards is not supported at this time.

View File

@@ -16,8 +16,6 @@ This page explains how to install Grafana dependencies, download and install Gra
While the process for upgrading Grafana is very similar to installing Grafana, there are some key backup steps you should perform. Read [Upgrading Grafana]({{< relref "../upgrade-grafana/" >}}) for tips and guidance on updating an existing installation.
> **Note:** You can use [Grafana Cloud](https://grafana.com/products/cloud/features/#cloud-logs) to avoid the overhead of installing, maintaining, and scaling your observability stack. The free forever plan includes Grafana, 10K Prometheus series, 50 GB logs, and more.[Create a free account to get started](https://grafana.com/auth/sign-up/create-user?pg=docs-grafana-install&plcmt=in-text).
## 1. Download and install
You can install Grafana using our official APT repository, by downloading a `.deb` package, or by downloading a binary `.tar.gz` file.

View File

@@ -17,8 +17,6 @@ This topic explains how to install Grafana dependencies, download and install Gr
While the process for upgrading Grafana is very similar to installing Grafana, there are some key backup steps you should perform. Read [Upgrading Grafana]({{< relref "../upgrade-grafana/" >}}) for tips and guidance on updating an existing installation.
> **Note:** You can use [Grafana Cloud](https://grafana.com/products/cloud/features/#cloud-logs) to avoid the overhead of installing, maintaining, and scaling your observability stack. The free forever plan includes Grafana, 10K Prometheus series, 50 GB logs, and more.[Create a free account to get started](https://grafana.com/auth/sign-up/create-user?pg=docs-grafana-install&plcmt=in-text).
## 1. Download and install
You can install Grafana from a YUM repository, manually using YUM, manually using RPM, or by downloading a binary `.tar.gz` file.

View File

@@ -404,3 +404,7 @@ The concept of a `default` data source existed in Grafana since the beginning. H
This behavior was not very intuitive and creates issues for users who want to change the default without it impacting existing dashboards.
That is why we are changing the behavior in 8.5. From now on, the `default` data source will not be a persisted property but just the starting data source for new panels and queries.
Existing dashboards that still have panels with a `datasource` set to null will be migrated when the dashboard opens. The migration will set the data source property to the **current** default data source.
## Upgrading to v9.2
Beginning in v9.2, Grafana has a [supported database versions policy]({{< relref "./installation/#supported-databases" >}}). As of this release, MySQL versions from 5.7, postgres versions from v10, and SQLite 3 are supported databases.

View File

@@ -7,5 +7,3 @@ title: Grafana Cloud
## Grafana Cloud
Grafana Cloud is a highly available, fast, fully managed OpenSaaS logging and metrics platform. It is everything you love about Grafana, but Grafana Labs hosts it for you and handles all the headaches.
[Learn more about Grafana Cloud](https://grafana.com/cloud/) and get started with your [free account with Grafana Cloud](https://grafana.com/signup/cloud/connect-account?pg=gsdocs) that includes a robust free tier with access to 10k metrics, 50GB logs, 50GB traces, 2 weeks data retention and 3 users.

View File

@@ -123,7 +123,7 @@ Query caching advantages:
Caching currently works for all backend data sources. You can enable the cache globally or per data source, and you can configure the cache duration per data source. The cache is currently in-memory.
For more information, refer to [Query caching]({{< relref "../enterprise/query-caching/" >}}).
For more information, refer to [Query caching]({{< relref "../administration/data-source-management/#query-caching" >}}).
### Use template variable in reports

View File

@@ -304,7 +304,7 @@ This results in faster average load times for dashboards and fewer duplicate que
You can enable caching per data source, and time-to-live (TTL) can be configured globally and per data source. Query caching can be set up with Redis, Memcached, or a simple in-memory cache.
For more information, refer to the [Data source query caching docs]({{< relref "../enterprise/query-caching/" >}}).
For more information, refer to the [Data source query caching docs]({{< relref "../administration/data-source-management/#query-caching" >}}).
### Reporting updates

View File

@@ -154,7 +154,7 @@ Weve enhanced the scheduler for Reports to be more flexible, so you can send
### Encrypt data in the query cache
Query caching was released in Grafana 8.0 and allows you to temporarily store the results of data source queries in a cache, so that Grafana reads repeated queries from there instead of from the data source itself. This reduces load on data sources, improves dashboard load times, and can save money for data sources that charge per query. To learn more about query caching see its [overview]({{< relref "../enterprise/query-caching/" >}}) page. To find out how to turn on encryption, refer to the [caching configuration]({{< relref "../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}) documentation.
Query caching was released in Grafana 8.0 and allows you to temporarily store the results of data source queries in a cache, so that Grafana reads repeated queries from there instead of from the data source itself. This reduces load on data sources, improves dashboard load times, and can save money for data sources that charge per query. To learn more about query caching see its [overview]({{< relref "../administration/data-source-management/#query-caching" >}}) page. To find out how to turn on encryption, refer to the [caching configuration]({{< relref "../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}) documentation.
You can now encrypt the query data cached by Grafana. This improves the security of query data, especially when your cache (like Redis) is shared with other services.

View File

@@ -41,7 +41,7 @@ All functions, aggregations and binary operations are added via the + Operation
### Range vector
The query builder will automatically mange and add the range selector. It will be shown as a parameter to the operations that require a range vector (rate, delta, increase, etc).
The query builder will automatically manage and add the range selector. It will be shown as a parameter to the operations that require a range vector (rate, delta, increase, etc).
### Binary operations

View File

@@ -31,7 +31,7 @@ Service accounts are an evolution in machine access within Grafana.
You can create multiple API tokens per service account with independent expiration dates, and temporarily disable a service account without deleting it.
These benefits make service accounts a more flexible way for Terraform and other apps to authenticate with Grafana.
Service accounts also work with [role-based access control]({{< relref "../administration/roles-and-permissions/access-control" >}}) in [Grafana Enterprise]({{< relref "../enterprise/" >}}).
Service accounts also work with [role-based access control]({{< relref "../administration/roles-and-permissions/access-control" >}}) in [Grafana Enterprise]({{< relref "../introduction/grafana-enterprise" >}}).
You can improve security by granting service accounts specific roles to limit the functions they can perform.
Service accounts have been in beta since Grafana v8.5.
During that time, we've improved the UI and migration path from API keys, made it possible to add service accounts to teams, and inherit team permissions.

View File

@@ -219,3 +219,19 @@ For more information, see the [SAML configuration documentation](https://grafana
You can now map OAuth groups and roles to Server Admin for the GitLab, GitHub, AzureAD, Okta, and Generic OAuth integrations.
To enable this functionality, set the `allow_assign_grafana_admin` configuration option to `true` in the desired OAuth integration section.
For more information, see the [authentication configuration documentation](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/) for each OAuth client.
## Match parameter support in prometheus labels API
Prometheus users running Prometheus v2.24 and higher can use the [labels endpoint](https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values) instead of the [series endpoint](https://prometheus.io/docs/prometheus/latest/querying/api/#finding-series-by-label-matchers) for the [`label_values` function]({{< relref "../datasources/prometheus/#query-variable" >}}).
This decreases load times for templated high-cardinality Prometheus instances.
If you want to benefit from this endpoint you must first configure the Prometheus type and version in any Prometheus data sources' [configuration]({{< relref "../datasources/prometheus/" >}}).
## New Prometheus streaming parser
In Grafana v9.2, you can enable the `prometheusStreamingJSONParser` [feature toggle]({{< relref "../setup-grafana/configure-grafana/#feature_toggles" >}}) to use a better-performing, memory-efficient streaming JSON client for Prometheus.
We'll make this client the default in Grafana v9.3.
When Prometheus returns `NaN` values, this new client doesn't change them, neither to the value `null` nor to `0` as in recent Grafana versions.
If you use this new Prometheus streaming parser with Grafana Managed Alerts, this change in behavior might trigger alerts.
To avoid this, select the "Drop non-numeric values" option in the Reduce expression to drop `NaN` values.

View File

@@ -16,7 +16,7 @@ e2e.scenario({
itName: 'Tests dashboard time zone scenarios',
addScenarioDataSource: false,
addScenarioDashBoard: false,
skipScenario: false,
skipScenario: true,
scenario: () => {
e2e.flows.openDashboard({ uid: '5SdHCasdf' });

View File

@@ -10,7 +10,7 @@ const addDataSource = () => {
e2e.components.DataSource.Prometheus.configPage.exemplarsAddButton().click();
e2e.components.DataSource.Prometheus.configPage.internalLinkSwitch().check({ force: true });
e2e.components.DataSource.DataSourceHttpSettings.urlInput().type('http://prom-url:9090');
e2e.components.DataSourcePicker.inputV2().should('be.visible').click({ force: true });
e2e.components.DataSourcePicker.inputV2().click({ force: true }).should('have.focus');
e2e().contains('gdev-tempo').scrollIntoView().should('be.visible').click();
},

4
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/grafana/grafana
go 1.18
go 1.19
// Override xorm's outdated go-mssqldb dependency, since we can't upgrade to current xorm (due to breaking changes).
// We need a more current go-mssqldb so we get rid of a version of apache/thrift with vulnerabilities.
@@ -230,7 +230,7 @@ require (
go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.12 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/text v0.3.7
golang.org/x/text v0.4.0
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3

2
go.sum
View File

@@ -3089,6 +3089,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@@ -4,5 +4,5 @@
"packages": [
"packages/*"
],
"version": "9.2.2"
"version": "9.2.4"
}

View File

@@ -3,7 +3,7 @@
"license": "AGPL-3.0-only",
"private": true,
"name": "grafana",
"version": "9.2.2",
"version": "9.2.4",
"repository": "github:grafana/grafana",
"scripts": {
"api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js",
@@ -190,7 +190,6 @@
"eslint-plugin-react-hooks": "4.6.0",
"eslint-webpack-plugin": "3.2.0",
"expose-loader": "4.0.0",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "7.2.13",
"fs-extra": "10.1.0",
"glob": "8.0.3",
@@ -217,7 +216,6 @@
"postcss-reporter": "7.0.5",
"postcss-scss": "4.0.4",
"prettier": "2.7.1",
"raw-loader": "4.0.2",
"react-refresh": "0.14.0",
"react-select-event": "5.5.0",
"react-simple-compat": "1.2.3",
@@ -406,11 +404,21 @@
},
"resolutions": {
"underscore": "1.13.4",
"@mdx-js/loader/loader-utils": "^2.0.0",
"@types/slate": "0.47.9",
"@rushstack/node-core-library": "3.52.0",
"@rushstack/rig-package": "0.3.13",
"@rushstack/ts-command-line": "4.12.1",
"@storybook/builder-webpack4/css-loader": "6.7.1",
"@storybook/builder-webpack4/html-webpack-plugin": "5.5.0",
"@storybook/builder-webpack4/webpack": "5.74.0",
"@storybook/core-common/webpack": "5.74.0",
"@storybook/core-server/webpack": "5.74.0",
"@storybook/manager-webpack4/css-loader": "6.7.1",
"@storybook/manager-webpack4/html-webpack-plugin": "5.5.0",
"@storybook/manager-webpack4/webpack": "5.74.0",
"@storybook/react/webpack": "5.74.0",
"ngtemplate-loader/loader-utils": "^2.0.0",
"node-fetch": "2.6.7",
"slate-dev-environment@^0.2.2": "patch:slate-dev-environment@npm:0.2.5#.yarn/patches/slate-dev-environment-npm-0.2.5-9aeb7da7b5.patch"
},

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/data",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana Data Library",
"keywords": [
"typescript"
@@ -34,7 +34,7 @@
},
"dependencies": {
"@braintree/sanitize-url": "6.0.0",
"@grafana/schema": "9.2.2",
"@grafana/schema": "9.2.4",
"@types/d3-interpolate": "^1.4.0",
"d3-interpolate": "1.4.0",
"date-fns": "2.29.1",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e-selectors",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana End-to-End Test Selectors Library",
"keywords": [
"cli",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana End-to-End Test Library",
"keywords": [
"cli",
@@ -61,7 +61,7 @@
"@babel/core": "7.19.0",
"@babel/preset-env": "7.19.0",
"@cypress/webpack-preprocessor": "5.12.0",
"@grafana/e2e-selectors": "9.2.2",
"@grafana/e2e-selectors": "9.2.4",
"@grafana/tsconfig": "^1.2.0-rc1",
"@mochajs/json-file-reporter": "^1.2.0",
"babel-loader": "8.2.5",
@@ -77,7 +77,7 @@
"resolve-as-bin": "2.1.0",
"rimraf": "3.0.2",
"tracelib": "1.0.1",
"ts-loader": "6.2.2",
"ts-loader": "8.4.0",
"tslib": "2.4.0",
"typescript": "4.8.2",
"uuid": "8.3.2",

View File

@@ -90,7 +90,13 @@ export const configurePanel = (config: PartialAddPanelConfig | PartialEditPanelC
e2e.components.Panels.Panel.title(panelTitle).click();
e2e.components.Panels.Panel.headerItems('Edit').click();
} else {
e2e.components.PageToolbar.item('Add panel').click();
try {
e2e.components.PageToolbar.item('Add panel').click();
} catch (e) {
// Depending on the screen size, the "Add panel" button might be hidden
e2e.components.PageToolbar.item('Show more items').click();
e2e.components.PageToolbar.item('Add panel').last().click();
}
e2e.pages.AddDashboard.addNewPanel().click();
}

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/runtime",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana Runtime Library",
"keywords": [
"grafana",
@@ -36,9 +36,9 @@
},
"dependencies": {
"@grafana/agent-web": "^0.4.0",
"@grafana/data": "9.2.2",
"@grafana/e2e-selectors": "9.2.2",
"@grafana/ui": "9.2.2",
"@grafana/data": "9.2.4",
"@grafana/e2e-selectors": "9.2.4",
"@grafana/ui": "9.2.4",
"@sentry/browser": "6.19.7",
"history": "4.10.1",
"lodash": "4.17.21",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/schema",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana Schema Library",
"keywords": [
"typescript"

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/toolkit",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana Toolkit",
"keywords": [
"grafana",
@@ -50,10 +50,10 @@
"@babel/preset-env": "7.18.9",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@grafana/data": "9.2.2",
"@grafana/data": "9.2.4",
"@grafana/eslint-config": "5.0.0",
"@grafana/tsconfig": "^1.2.0-rc1",
"@grafana/ui": "9.2.2",
"@grafana/ui": "9.2.4",
"@jest/core": "27.5.1",
"@types/command-exists": "^1.2.0",
"@types/eslint": "8.4.1",
@@ -85,7 +85,6 @@
"eslint-plugin-react": "7.29.4",
"eslint-plugin-react-hooks": "4.6.0",
"execa": "^5.1.1",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"fs-extra": "^10.0.0",
"globby": "^11.0.4",
@@ -122,7 +121,6 @@
"ts-node": "^9.1.0",
"tslib": "2.4.0",
"typescript": "4.8.2",
"url-loader": "^4.1.1",
"webpack": "^5.72.0"
}
}

View File

@@ -94,7 +94,9 @@ export const getStyleLoaders = () => {
{
loader: require.resolve('less-loader'),
options: {
javascriptEnabled: true,
lessOptions: {
javascriptEnabled: true,
},
},
},
],

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/ui",
"version": "9.2.2",
"version": "9.2.4",
"description": "Grafana Components Library",
"keywords": [
"grafana",
@@ -47,9 +47,9 @@
"dependencies": {
"@emotion/css": "11.9.0",
"@emotion/react": "11.9.3",
"@grafana/data": "9.2.2",
"@grafana/e2e-selectors": "9.2.2",
"@grafana/schema": "9.2.2",
"@grafana/data": "9.2.4",
"@grafana/e2e-selectors": "9.2.4",
"@grafana/schema": "9.2.4",
"@monaco-editor/react": "4.4.5",
"@popperjs/core": "2.11.5",
"@react-aria/button": "3.6.1",
@@ -178,7 +178,6 @@
"process": "^0.11.10",
"raw-loader": "4.0.2",
"react": "17.0.2",
"react-docgen-typescript-loader": "3.7.2",
"react-dom": "17.0.2",
"react-test-renderer": "17.0.2",
"rimraf": "3.0.2",

View File

@@ -129,6 +129,7 @@ Object {
],
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",
@@ -152,6 +153,7 @@ Object {
],
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",
@@ -175,6 +177,7 @@ Object {
],
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",
@@ -198,6 +201,7 @@ Object {
],
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",
@@ -221,6 +225,7 @@ Object {
],
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",

View File

@@ -36,7 +36,7 @@ export default function resetSelectStyles(theme: GrafanaTheme2) {
option: () => ({}),
placeholder: (originalStyles: CSSObjectWithLabel) => ({
...originalStyles,
color: theme.colors.text.disabled,
color: theme.colors.text.secondary,
}),
singleValue: () => ({}),
valueContainer: () => ({}),

View File

@@ -0,0 +1,275 @@
import { ArrayVector, FieldType } from '@grafana/data';
import { getTheme } from '@grafana/ui';
import { preparePlotConfigBuilder } from './utils';
describe('when fill below to option is used', () => {
// eslint-disable-next-line
let eventBus: any;
// eslint-disable-next-line
let renderers: any[];
// eslint-disable-next-line
let tests: any;
beforeEach(() => {
eventBus = {
publish: jest.fn(),
getStream: jest.fn(),
subscribe: jest.fn(),
removeAllListeners: jest.fn(),
newScopedBus: jest.fn(),
};
renderers = [];
tests = [
{
alignedFrame: {
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'Time',
state: { multipleFrames: true, displayName: 'Time', origin: { fieldIndex: 0, frameIndex: 0 } },
type: FieldType.time,
},
{
config: { displayNameFromDS: 'Test1', custom: { fillBelowTo: 'Test2' }, min: 0, max: 100 },
values: new ArrayVector([1, 2, 3]),
name: 'Value',
state: { multipleFrames: true, displayName: 'Test1', origin: { fieldIndex: 1, frameIndex: 0 } },
type: FieldType.number,
},
{
config: { displayNameFromDS: 'Test2', min: 0, max: 100 },
values: new ArrayVector([4, 5, 6]),
name: 'Value',
state: { multipleFrames: true, displayName: 'Test2', origin: { fieldIndex: 1, frameIndex: 1 } },
type: FieldType.number,
},
],
length: 3,
},
allFrames: [
{
name: 'Test1',
refId: 'A',
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'Time',
state: { multipleFrames: true, displayName: 'Time', origin: { fieldIndex: 0, frameIndex: 0 } },
type: FieldType.time,
},
{
config: { displayNameFromDS: 'Test1', custom: { fillBelowTo: 'Test2' }, min: 0, max: 100 },
values: new ArrayVector([1, 2, 3]),
name: 'Value',
state: { multipleFrames: true, displayName: 'Test1', origin: { fieldIndex: 1, frameIndex: 0 } },
type: FieldType.number,
},
],
length: 2,
},
{
name: 'Test2',
refId: 'B',
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'Time',
state: { multipleFrames: true, displayName: 'Time', origin: { fieldIndex: 0, frameIndex: 1 } },
type: FieldType.time,
},
{
config: { displayNameFromDS: 'Test2', min: 0, max: 100 },
values: new ArrayVector([1, 2, 3]),
name: 'Value',
state: { multipleFrames: true, displayName: 'Test2', origin: { fieldIndex: 1, frameIndex: 1 } },
type: FieldType.number,
},
],
length: 2,
},
],
expectedResult: 1,
},
{
alignedFrame: {
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'time',
state: { multipleFrames: true, displayName: 'time', origin: { fieldIndex: 0, frameIndex: 0 } },
type: FieldType.time,
},
{
config: { custom: { fillBelowTo: 'below_value1' } },
values: new ArrayVector([1, 2, 3]),
name: 'value1',
state: { multipleFrames: true, displayName: 'value1', origin: { fieldIndex: 1, frameIndex: 0 } },
type: FieldType.number,
},
{
config: { custom: { fillBelowTo: 'below_value2' } },
values: new ArrayVector([4, 5, 6]),
name: 'value2',
state: { multipleFrames: true, displayName: 'value2', origin: { fieldIndex: 2, frameIndex: 0 } },
type: FieldType.number,
},
{
config: {},
values: new ArrayVector([4, 5, 6]),
name: 'below_value1',
state: { multipleFrames: true, displayName: 'below_value1', origin: { fieldIndex: 1, frameIndex: 1 } },
type: FieldType.number,
},
{
config: {},
values: new ArrayVector([4, 5, 6]),
name: 'below_value2',
state: { multipleFrames: true, displayName: 'below_value2', origin: { fieldIndex: 2, frameIndex: 1 } },
type: FieldType.number,
},
],
length: 5,
},
allFrames: [
{
refId: 'A',
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'time',
state: { multipleFrames: true, displayName: 'time', origin: { fieldIndex: 0, frameIndex: 0 } },
type: FieldType.time,
},
{
config: { custom: { fillBelowTo: 'below_value1' } },
values: new ArrayVector([1, 2, 3]),
name: 'value1',
state: { multipleFrames: true, displayName: 'value1', origin: { fieldIndex: 1, frameIndex: 0 } },
type: FieldType.number,
},
{
config: { custom: { fillBelowTo: 'below_value2' } },
values: new ArrayVector([4, 5, 6]),
name: 'value2',
state: { multipleFrames: true, displayName: 'value2', origin: { fieldIndex: 2, frameIndex: 0 } },
type: FieldType.number,
},
],
length: 3,
},
{
refId: 'B',
fields: [
{
config: {},
values: new ArrayVector([1667406900000, 1667407170000, 1667407185000]),
name: 'time',
state: { multipleFrames: true, displayName: 'time', origin: { fieldIndex: 0, frameIndex: 1 } },
type: FieldType.time,
},
{
config: {},
values: new ArrayVector([4, 5, 6]),
name: 'below_value1',
state: { multipleFrames: true, displayName: 'below_value1', origin: { fieldIndex: 1, frameIndex: 1 } },
type: FieldType.number,
},
{
config: {},
values: new ArrayVector([4, 5, 6]),
name: 'below_value2',
state: { multipleFrames: true, displayName: 'below_value2', origin: { fieldIndex: 2, frameIndex: 1 } },
type: FieldType.number,
},
],
length: 3,
},
],
expectedResult: 2,
},
];
});
it('should verify if fill below to is set then builder bands are set', () => {
for (const test of tests) {
const builder = preparePlotConfigBuilder({
frame: test.alignedFrame,
//@ts-ignore
theme: getTheme(),
timeZones: ['browser'],
getTimeRange: jest.fn(),
eventBus,
sync: jest.fn(),
allFrames: test.allFrames,
renderers,
});
//@ts-ignore
expect(builder.bands.length).toBe(test.expectedResult);
}
});
it('should verify if fill below to is not set then builder bands are empty', () => {
tests[0].alignedFrame.fields[1].config.custom.fillBelowTo = undefined;
tests[0].allFrames[0].fields[1].config.custom.fillBelowTo = undefined;
tests[1].alignedFrame.fields[1].config.custom.fillBelowTo = undefined;
tests[1].alignedFrame.fields[2].config.custom.fillBelowTo = undefined;
tests[1].allFrames[0].fields[1].config.custom.fillBelowTo = undefined;
tests[1].allFrames[0].fields[2].config.custom.fillBelowTo = undefined;
tests[0].expectedResult = 0;
tests[1].expectedResult = 0;
for (const test of tests) {
const builder = preparePlotConfigBuilder({
frame: test.alignedFrame,
//@ts-ignore
theme: getTheme(),
timeZones: ['browser'],
getTimeRange: jest.fn(),
eventBus,
sync: jest.fn(),
allFrames: test.allFrames,
renderers,
});
//@ts-ignore
expect(builder.bands.length).toBe(test.expectedResult);
}
});
it('should verify if fill below to is set and field name is overriden then builder bands are set', () => {
tests[0].alignedFrame.fields[2].config.displayName = 'newName';
tests[0].alignedFrame.fields[2].state.displayName = 'newName';
tests[0].allFrames[1].fields[1].config.displayName = 'newName';
tests[0].allFrames[1].fields[1].state.displayName = 'newName';
tests[1].alignedFrame.fields[3].config.displayName = 'newName';
tests[1].alignedFrame.fields[3].state.displayName = 'newName';
tests[1].allFrames[1].fields[1].config.displayName = 'newName';
tests[1].allFrames[1].fields[1].state.displayName = 'newName';
for (const test of tests) {
const builder = preparePlotConfigBuilder({
frame: test.alignedFrame,
//@ts-ignore
theme: getTheme(),
timeZones: ['browser'],
getTimeRange: jest.fn(),
eventBus,
sync: jest.fn(),
allFrames: test.allFrames,
renderers,
});
//@ts-ignore
expect(builder.bands.length).toBe(test.expectedResult);
}
});
});

View File

@@ -296,7 +296,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
let pointsFilter: uPlot.Series.Points.Filter = () => null;
if (customConfig.spanNulls !== true) {
if (customConfig.spanNulls !== true && showPoints !== VisibilityMode.Always) {
pointsFilter = (u, seriesIdx, show, gaps) => {
let filtered = [];
@@ -400,8 +400,19 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
}
if (customConfig.fillBelowTo) {
const fillBelowToField = frame.fields.find(
(f) =>
customConfig.fillBelowTo === f.name ||
customConfig.fillBelowTo === f.config?.displayNameFromDS ||
customConfig.fillBelowTo === getFieldDisplayName(f, frame, allFrames)
);
const fillBelowDispName = fillBelowToField
? getFieldDisplayName(fillBelowToField, frame, allFrames)
: customConfig.fillBelowTo;
const t = indexByName.get(dispName);
const b = indexByName.get(customConfig.fillBelowTo);
const b = indexByName.get(fillBelowDispName);
if (isNumber(b) && isNumber(t)) {
builder.addBand({
series: [t, b],
@@ -423,7 +434,40 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
dynamicSeriesColor = (seriesIdx) => getFieldSeriesColor(alignedFrame.fields[seriesIdx], theme).color;
}
// this adds leading and trailing gaps when datasets have leading and trailing nulls
// it will cause additional unnecessary clips, but we also use adjacent gaps to show single points
// when not connecting across gaps, e.g. null,100,null,null,50,50,50,null,50,null,null
const gapsRefiner: uPlot.Series.GapsRefiner = (u, seriesIdx, idx0, idx1, gaps) => {
let yData = u.data[seriesIdx];
// @ts-ignore
let xData = u._data[0];
// scan to first and last non-null vals
let first = idx0,
last = idx1;
while (first <= last && yData[first] == null) {
first++;
}
while (last > first && yData[last] == null) {
last--;
}
if (first !== idx0) {
gaps.unshift([u.bbox.left, Math.round(u.valToPos(xData[first]!, 'x', true))]);
}
if (last !== idx1) {
gaps.push([Math.round(u.valToPos(xData[last]!, 'x', true)), u.bbox.left + u.bbox.width]);
}
return gaps;
};
builder.addSeries({
gapsRefiner,
pathBuilder,
pointsBuilder,
scaleKey,

View File

@@ -613,6 +613,7 @@ describe('UPlotConfigBuilder', () => {
Object {
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#0000ff",
@@ -740,6 +741,7 @@ describe('UPlotConfigBuilder', () => {
Object {
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#0000ff",
@@ -758,6 +760,7 @@ describe('UPlotConfigBuilder', () => {
Object {
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#00ff00",
@@ -776,6 +779,7 @@ describe('UPlotConfigBuilder', () => {
Object {
"facets": undefined,
"fill": [Function],
"gaps": [Function],
"paths": [Function],
"points": Object {
"fill": "#ff0000",

View File

@@ -49,6 +49,8 @@ export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsCo
dataFrameFieldIndex?: DataFrameFieldIndex;
theme: GrafanaTheme2;
value?: uPlot.Series.Value;
gapsRefiner?: uPlot.Series.GapsRefiner;
}
export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
@@ -71,6 +73,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
pxAlign,
spanNulls,
show = true,
gapsRefiner,
} = this.props;
let lineConfig: Partial<Series> = {};
@@ -145,6 +148,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
pxAlign,
show,
fill: this.getFill(),
gaps: gapsRefiner ?? ((u, seriesIdx, idx0, idx1, gaps) => gaps),
...lineConfig,
...pointsConfig,
};

View File

@@ -1063,7 +1063,7 @@ describe('auto stacking groups', () => {
},
{
name: 'd',
values: [-0, -10, -20],
values: [null, -0, null],
config: { custom: { stacking: { mode: StackingMode.Normal } } },
},
],

View File

@@ -116,8 +116,7 @@ export function getStackingGroups(frame: DataFrame) {
// will this be stacked up or down after any transforms applied
let vals = values.toArray();
let transform = custom.transform;
let firstValue = vals.find((v) => v != null);
let stackDir = getStackDirection(transform, firstValue);
let stackDir = getStackDirection(transform, vals);
let drawStyle = custom.drawStyle as GraphDrawStyle;
let drawStyle2 =
@@ -341,13 +340,48 @@ export function findMidPointYPosition(u: uPlot, idx: number) {
return y;
}
function getStackDirection(transform: GraphTransform, firstValue: number) {
// Check if first value is negative zero. This can happen with a binary operation transform.
const isNegativeZero = Object.is(firstValue, -0);
function getStackDirection(transform: GraphTransform, data: unknown[]) {
const hasNegSamp = hasNegSample(data);
if (transform === GraphTransform.NegativeY) {
return !isNegativeZero && firstValue >= 0 ? StackDirection.Neg : StackDirection.Pos;
return hasNegSamp ? StackDirection.Pos : StackDirection.Neg;
}
return !isNegativeZero && firstValue >= 0 ? StackDirection.Pos : StackDirection.Neg;
return hasNegSamp ? StackDirection.Neg : StackDirection.Pos;
}
// similar to isLikelyAscendingVector()
function hasNegSample(data: unknown[], samples = 50) {
const len = data.length;
if (len === 0) {
return false;
}
// skip leading & trailing nullish
let firstIdx = 0;
let lastIdx = len - 1;
while (firstIdx <= lastIdx && data[firstIdx] == null) {
firstIdx++;
}
while (lastIdx >= firstIdx && data[lastIdx] == null) {
lastIdx--;
}
if (lastIdx >= firstIdx) {
const stride = Math.max(1, Math.floor((lastIdx - firstIdx + 1) / samples));
for (let i = firstIdx; i <= lastIdx; i += stride) {
const v = data[i];
if (v != null && (v < 0 || Object.is(v, -0))) {
return true;
}
}
}
return false;
}
// Dev helpers

View File

@@ -1,6 +1,6 @@
{
"name": "@jaegertracing/jaeger-ui-components",
"version": "9.2.2",
"version": "9.2.4",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,10 +31,10 @@
},
"dependencies": {
"@emotion/css": "11.9.0",
"@grafana/data": "9.2.2",
"@grafana/e2e-selectors": "9.2.2",
"@grafana/runtime": "9.2.2",
"@grafana/ui": "9.2.2",
"@grafana/data": "9.2.4",
"@grafana/e2e-selectors": "9.2.4",
"@grafana/runtime": "9.2.4",
"@grafana/ui": "9.2.4",
"chance": "^1.0.10",
"classnames": "^2.2.5",
"combokeys": "^3.0.0",

View File

@@ -26,10 +26,8 @@ ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bi
WORKDIR $GF_PATHS_HOME
RUN apk add --no-cache ca-certificates bash tzdata && \
apk add --no-cache musl-utils
RUN apk add --no-cache openssl --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
RUN apk add --no-cache ca-certificates bash tzdata musl-utils
RUN apk info -vv | sort
# Oracle Support for x86_64 only
RUN if [ `arch` = "x86_64" ]; then \

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
@@ -37,6 +38,10 @@ func (hs *HTTPServer) AdminCreateUser(c *models.ReqContext) response.Response {
if err := web.Bind(c.Req, &form); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
form.Email = strings.TrimSpace(form.Email)
form.Login = strings.TrimSpace(form.Login)
cmd := user.CreateUserCommand{
Login: form.Login,
Email: form.Email,

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
@@ -217,21 +218,37 @@ func (hs *HTTPServer) GetInviteInfoByCode(c *models.ReqContext) response.Respons
func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response {
completeInvite := dtos.CompleteInviteForm{}
if err := web.Bind(c.Req, &completeInvite); err != nil {
var err error
if err = web.Bind(c.Req, &completeInvite); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
query := models.GetTempUserByCodeQuery{Code: completeInvite.InviteCode}
completeInvite.Email, err = ValidateAndNormalizeEmail(completeInvite.Email)
if err != nil {
return response.Error(http.StatusBadRequest, "Invalid email address provided", nil)
}
completeInvite.Username = strings.TrimSpace(completeInvite.Username)
query := models.GetTempUserByCodeQuery{Code: completeInvite.InviteCode}
if err := hs.tempUserService.GetTempUserByCode(c.Req.Context(), &query); err != nil {
if errors.Is(err, models.ErrTempUserNotFound) {
return response.Error(404, "Invite not found", nil)
return response.Error(http.StatusNotFound, "Invite not found", nil)
}
return response.Error(500, "Failed to get invite", err)
return response.Error(http.StatusInternalServerError, "Failed to get invite", err)
}
invite := query.Result
if invite.Status != models.TmpUserInvitePending {
return response.Error(412, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil)
return response.Error(http.StatusPreconditionFailed, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil)
}
// In case the user is invited by email address
if inviteMail, err := ValidateAndNormalizeEmail(invite.Email); err == nil {
// Make sure that the email address is not amended
if completeInvite.Email != inviteMail {
return response.Error(http.StatusBadRequest, "The provided email is different from the address that is found in the invite", nil)
}
}
cmd := user.CreateUserCommand{

View File

@@ -28,8 +28,8 @@ func (hs *HTTPServer) SendResetPasswordEmail(c *models.ReqContext) response.Resp
usr, err := hs.userService.GetByLogin(c.Req.Context(), &userQuery)
if err != nil {
c.Logger.Info("Requested password reset for user that was not found", "user", userQuery.LoginOrEmail)
return response.Error(http.StatusOK, "Email sent", err)
c.Logger.Info("Requested password reset for user that was not found", "user", userQuery.LoginOrEmail, "error", err)
return response.Error(http.StatusOK, "Email sent", nil)
}
if usr.IsDisabled {

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"net/http"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
@@ -27,15 +28,21 @@ func GetSignUpOptions(c *models.ReqContext) response.Response {
// POST /api/user/signup
func (hs *HTTPServer) SignUp(c *models.ReqContext) response.Response {
form := dtos.SignUpForm{}
if err := web.Bind(c.Req, &form); err != nil {
var err error
if err = web.Bind(c.Req, &form); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
if !setting.AllowUserSignUp {
return response.Error(401, "User signup is disabled", nil)
}
form.Email, err = ValidateAndNormalizeEmail(form.Email)
if err != nil {
return response.Error(http.StatusBadRequest, "Invalid email address", nil)
}
existing := user.GetUserByLoginQuery{LoginOrEmail: form.Email}
_, err := hs.userService.GetByLogin(c.Req.Context(), &existing)
_, err = hs.userService.GetByLogin(c.Req.Context(), &existing)
if err == nil {
return response.Error(422, "User with same email address already exists", nil)
}
@@ -76,6 +83,9 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response {
return response.Error(401, "User signup is disabled", nil)
}
form.Email = strings.TrimSpace(form.Email)
form.Username = strings.TrimSpace(form.Username)
createUserCmd := user.CreateUserCommand{
Email: form.Email,
Login: form.Username,

View File

@@ -5,6 +5,7 @@ import (
"errors"
"net/http"
"strconv"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
@@ -116,9 +117,14 @@ func (hs *HTTPServer) GetUserByLoginOrEmail(c *models.ReqContext) response.Respo
// 500: internalServerError
func (hs *HTTPServer) UpdateSignedInUser(c *models.ReqContext) response.Response {
cmd := user.UpdateUserCommand{}
if err := web.Bind(c.Req, &cmd); err != nil {
var err error
if err = web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
cmd.Email = strings.TrimSpace(cmd.Email)
cmd.Login = strings.TrimSpace(cmd.Login)
if setting.AuthProxyEnabled {
if setting.AuthProxyHeaderProperty == "email" && cmd.Email != c.Email {
return response.Error(400, "Not allowed to change email when auth proxy is using email property", nil)
@@ -146,13 +152,18 @@ func (hs *HTTPServer) UpdateSignedInUser(c *models.ReqContext) response.Response
func (hs *HTTPServer) UpdateUser(c *models.ReqContext) response.Response {
cmd := user.UpdateUserCommand{}
var err error
if err := web.Bind(c.Req, &cmd); err != nil {
if err = web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
cmd.Email = strings.TrimSpace(cmd.Email)
cmd.Login = strings.TrimSpace(cmd.Login)
cmd.UserID, err = strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", err)
}
return hs.handleUpdateUser(c.Req.Context(), cmd)
}
@@ -181,6 +192,16 @@ func (hs *HTTPServer) UpdateUserActiveOrg(c *models.ReqContext) response.Respons
}
func (hs *HTTPServer) handleUpdateUser(ctx context.Context, cmd user.UpdateUserCommand) response.Response {
// external user -> user data cannot be updated
isExternal, err := hs.isExternalUser(ctx, cmd.UserID)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to validate User", err)
}
if isExternal {
return response.Error(http.StatusForbidden, "User info cannot be updated for external Users", nil)
}
if len(cmd.Login) == 0 {
cmd.Login = cmd.Email
if len(cmd.Login) == 0 {
@@ -198,6 +219,20 @@ func (hs *HTTPServer) handleUpdateUser(ctx context.Context, cmd user.UpdateUserC
return response.Success("User updated")
}
func (hs *HTTPServer) isExternalUser(ctx context.Context, userID int64) (bool, error) {
getAuthQuery := models.GetAuthInfoQuery{UserId: userID}
var err error
if err = hs.authInfoService.GetAuthInfo(ctx, &getAuthQuery); err == nil {
return true, nil
}
if errors.Is(err, user.ErrUserNotFound) {
return false, nil
}
return false, err
}
// swagger:route GET /user/orgs signed_in_user getSignedInUserOrgList
//
// Organizations of the actual User.

View File

@@ -13,12 +13,15 @@ import (
"golang.org/x/oauth2"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/models"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/login/authinfoservice"
authinfostore "github.com/grafana/grafana/pkg/services/login/authinfoservice/database"
"github.com/grafana/grafana/pkg/services/login/logintest"
"github.com/grafana/grafana/pkg/services/searchusers"
"github.com/grafana/grafana/pkg/services/searchusers/filters"
"github.com/grafana/grafana/pkg/services/secrets/database"
@@ -194,3 +197,117 @@ func TestUserAPIEndpoint_userLoggedIn(t *testing.T) {
assert.Equal(t, 10, respJSON.Get("perPage").MustInt())
}, mock)
}
func TestHTTPServer_UpdateUser(t *testing.T) {
settings := setting.NewCfg()
sqlStore := sqlstore.InitTestDB(t)
hs := &HTTPServer{
Cfg: settings,
SQLStore: sqlStore,
AccessControl: acmock.New(),
}
updateUserCommand := user.UpdateUserCommand{
Email: fmt.Sprint("admin", "@test.com"),
Name: "admin",
Login: "admin",
UserID: 1,
}
updateUserScenario(t, updateUserContext{
desc: "Should return 403 when the current User is an external user",
url: "/api/users/1",
routePattern: "/api/users/:id",
cmd: updateUserCommand,
fn: func(sc *scenarioContext) {
sc.authInfoService.ExpectedUserAuth = &models.UserAuth{}
sc.fakeReqWithParams("PUT", sc.url, map[string]string{"id": "1"}).exec()
assert.Equal(t, 403, sc.resp.Code)
},
}, hs)
}
type updateUserContext struct {
desc string
url string
routePattern string
cmd user.UpdateUserCommand
fn scenarioFunc
}
func updateUserScenario(t *testing.T, ctx updateUserContext, hs *HTTPServer) {
t.Run(fmt.Sprintf("%s %s", ctx.desc, ctx.url), func(t *testing.T) {
sc := setupScenarioContext(t, ctx.url)
sc.authInfoService = &logintest.AuthInfoServiceFake{}
hs.authInfoService = sc.authInfoService
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
c.Req.Body = mockRequestBody(ctx.cmd)
c.Req.Header.Add("Content-Type", "application/json")
sc.context = c
sc.context.OrgID = testOrgID
sc.context.UserID = testUserID
return hs.UpdateUser(c)
})
sc.m.Put(ctx.routePattern, sc.defaultHandler)
ctx.fn(sc)
})
}
func TestHTTPServer_UpdateSignedInUser(t *testing.T) {
settings := setting.NewCfg()
sqlStore := sqlstore.InitTestDB(t)
hs := &HTTPServer{
Cfg: settings,
SQLStore: sqlStore,
AccessControl: acmock.New(),
}
updateUserCommand := user.UpdateUserCommand{
Email: fmt.Sprint("admin", "@test.com"),
Name: "admin",
Login: "admin",
UserID: 1,
}
updateSignedInUserScenario(t, updateUserContext{
desc: "Should return 403 when the current User is an external user",
url: "/api/users/",
routePattern: "/api/users/",
cmd: updateUserCommand,
fn: func(sc *scenarioContext) {
sc.authInfoService.ExpectedUserAuth = &models.UserAuth{}
sc.fakeReqWithParams("PUT", sc.url, map[string]string{"id": "1"}).exec()
assert.Equal(t, 403, sc.resp.Code)
},
}, hs)
}
func updateSignedInUserScenario(t *testing.T, ctx updateUserContext, hs *HTTPServer) {
t.Run(fmt.Sprintf("%s %s", ctx.desc, ctx.url), func(t *testing.T) {
sc := setupScenarioContext(t, ctx.url)
sc.authInfoService = &logintest.AuthInfoServiceFake{}
hs.authInfoService = sc.authInfoService
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
c.Req.Body = mockRequestBody(ctx.cmd)
c.Req.Header.Add("Content-Type", "application/json")
sc.context = c
sc.context.OrgID = testOrgID
sc.context.UserID = testUserID
return hs.UpdateSignedInUser(c)
})
sc.m.Put(ctx.routePattern, sc.defaultHandler)
ctx.fn(sc)
})
}

View File

@@ -1,9 +1,25 @@
package api
import "encoding/json"
import (
"encoding/json"
"net/mail"
)
func jsonMap(data []byte) (map[string]string, error) {
jsonMap := make(map[string]string)
err := json.Unmarshal(data, &jsonMap)
return jsonMap, err
}
func ValidateAndNormalizeEmail(email string) (string, error) {
if email == "" {
return "", nil
}
e, err := mail.ParseAddress(email)
if err != nil {
return "", err
}
return e.Address, nil
}

View File

@@ -13,7 +13,11 @@ import (
func BuildFrontendPackages(c *cli.Context) error {
version := ""
if c.NArg() == 1 {
version = strings.TrimPrefix(c.Args().Get(0), "v")
// Fixes scenario where an incompatible semver is provided to lerna, which will cause the step to fail.
// When there is an invalid semver, a frontend package won't be published anyways.
if strings.Count(version, ".") == 2 {
version = strings.TrimPrefix(c.Args().Get(0), "v")
}
}
cfg, mode, err := frontend.GetConfig(c, version)

View File

@@ -69,7 +69,7 @@ func PublishPackages(c *cli.Context) error {
// In test release mode, the operator should configure different GCS buckets for the package repos,
// so should be safe.
if cfg.ReleaseMode.Mode == config.TagMode {
workDir, err := fsutil.CreateTempFile("")
workDir, err := fsutil.CreateTempDir("")
if err != nil {
return err
}

View File

@@ -24,3 +24,20 @@ func CreateTempFile(sfx string) (string, error) {
return f.Name(), nil
}
// CreateTempDir generates a temp directory, based on the provided suffix.
// A typical generated path looks like /var/folders/abcd/abcdefg/A/1137975807/.
func CreateTempDir(sfx string) (string, error) {
var suffix string
if sfx != "" {
suffix = fmt.Sprintf("*-%s", sfx)
} else {
suffix = sfx
}
dir, err := os.MkdirTemp("", suffix)
if err != nil {
return "", err
}
return dir, nil
}

View File

@@ -26,3 +26,23 @@ func TestCreateTempFile(t *testing.T) {
require.Len(t, strings.Split(pathParts[len(pathParts)-1], "-"), 2)
})
}
func TestCreateTempDir(t *testing.T) {
t.Run("empty suffix, expects pattern like: /var/folders/abcd/abcdefg/A/1137975807/", func(t *testing.T) {
filePath, err := CreateTempFile("")
require.NoError(t, err)
pathParts := strings.Split(filePath, "/")
require.Greater(t, len(pathParts), 1)
require.Len(t, strings.Split(pathParts[len(pathParts)-1], "-"), 1)
})
t.Run("non-empty suffix, expects /var/folders/abcd/abcdefg/A/1137975807-foobar/", func(t *testing.T) {
filePath, err := CreateTempFile("foobar")
require.NoError(t, err)
pathParts := strings.Split(filePath, "/")
require.Greater(t, len(pathParts), 1)
require.Len(t, strings.Split(pathParts[len(pathParts)-1], "-"), 2)
})
}

View File

@@ -122,7 +122,7 @@ func UpdateDebRepo(cfg PublishConfig, workDir string) error {
repoName = "beta"
}
repoRoot, err := fsutil.CreateTempFile("deb-repo")
repoRoot, err := fsutil.CreateTempDir("deb-repo")
if err != nil {
return err
}

View File

@@ -32,7 +32,7 @@ func UpdateRPMRepo(cfg PublishConfig, workDir string) error {
return err
}
repoRoot, err := fsutil.CreateTempFile("rpm-repo")
repoRoot, err := fsutil.CreateTempDir("rpm-repo")
if err != nil {
return err
}

View File

@@ -175,7 +175,7 @@ func executeServer(configFile, homePath, pidFile, packaging string, traceDiagnos
setting.IsEnterprise = extensions.IsEnterprise
setting.Packaging = validPackaging(packaging)
metrics.SetBuildInformation(opt.Version, opt.Commit, opt.BuildBranch)
metrics.SetBuildInformation(opt.Version, opt.Commit, opt.BuildBranch, buildstampInt64)
elevated, err := process.IsRunningWithElevatedPrivileges()
if err != nil {

View File

@@ -177,9 +177,6 @@ var (
// StatsTotalDashboardVersions is a metric of total number of dashboard versions stored in Grafana.
StatsTotalDashboardVersions prometheus.Gauge
// grafanaBuildVersion is a metric with a constant '1' value labeled by version, revision, branch, and goversion from which Grafana was built
grafanaBuildVersion *prometheus.GaugeVec
grafanaPluginBuildInfoDesc *prometheus.GaugeVec
// StatsTotalLibraryPanels is a metric of total number of library panels stored in Grafana.
@@ -497,12 +494,6 @@ func init() {
Namespace: ExporterName,
}, []string{"plugin_id"})
grafanaBuildVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "build_info",
Help: "A metric with a constant '1' value labeled by version, revision, branch, and goversion from which Grafana was built",
Namespace: ExporterName,
}, []string{"version", "revision", "branch", "goversion", "edition"})
grafanaPluginBuildInfoDesc = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "plugin_build_info",
Help: "A metric with a constant '1' value labeled by pluginId, pluginType and version from which Grafana plugin was built",
@@ -571,13 +562,28 @@ func init() {
}
// SetBuildInformation sets the build information for this binary
func SetBuildInformation(version, revision, branch string) {
func SetBuildInformation(version, revision, branch string, buildTimestamp int64) {
edition := "oss"
if setting.IsEnterprise {
edition = "enterprise"
}
grafanaBuildVersion := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "build_info",
Help: "A metric with a constant '1' value labeled by version, revision, branch, and goversion from which Grafana was built",
Namespace: ExporterName,
}, []string{"version", "revision", "branch", "goversion", "edition"})
grafanaBuildTimestamp := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "build_timestamp",
Help: "A metric exposing when the binary was built in epoch",
Namespace: ExporterName,
}, []string{"version", "revision", "branch", "goversion", "edition"})
prometheus.MustRegister(grafanaBuildVersion, grafanaBuildTimestamp)
grafanaBuildVersion.WithLabelValues(version, revision, branch, runtime.Version(), edition).Set(1)
grafanaBuildTimestamp.WithLabelValues(version, revision, branch, runtime.Version(), edition).Set(float64(buildTimestamp))
}
// SetEnvironmentInformation exposes environment values provided by the operators as an `_info` metric.
@@ -654,7 +660,6 @@ func initMetricVars() {
StatsTotalActiveEditors,
StatsTotalActiveAdmins,
StatsTotalDataSources,
grafanaBuildVersion,
grafanaPluginBuildInfoDesc,
StatsTotalDashboardVersions,
StatsTotalAnnotations,

View File

@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/database"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -239,3 +240,68 @@ func TestService_RegisterFixedRoles(t *testing.T) {
})
}
}
func TestPermissionCacheKey(t *testing.T) {
testcases := []struct {
name string
signedInUser *user.SignedInUser
expected string
expectedErr error
}{
{
name: "should return correct key for user",
signedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
},
expected: "rbac-permissions-1-user-1",
expectedErr: nil,
},
{
name: "should return correct key for api key",
signedInUser: &user.SignedInUser{
OrgID: 1,
ApiKeyID: 1,
IsServiceAccount: false,
},
expected: "rbac-permissions-1-apikey-1",
expectedErr: nil,
},
{
name: "should return correct key for service account",
signedInUser: &user.SignedInUser{
OrgID: 1,
UserID: 1,
IsServiceAccount: true,
},
expected: "rbac-permissions-1-service-1",
expectedErr: nil,
},
{
name: "should return correct key for matching a service account with userId -1",
signedInUser: &user.SignedInUser{
OrgID: 1,
UserID: -1,
IsServiceAccount: true,
},
expected: "rbac-permissions-1-service--1",
expectedErr: nil,
},
{
name: "should return error if not matching any",
signedInUser: &user.SignedInUser{
OrgID: 1,
UserID: -1,
},
expected: "",
expectedErr: user.ErrNoUniqueID,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
str, err := permissionCacheKey(tc.signedInUser)
require.Equal(t, tc.expectedErr, err)
assert.Equal(t, tc.expected, str)
})
}
}

View File

@@ -262,10 +262,10 @@ func (p *ResourcePermission) Contains(targetActions []string) bool {
}
type SetResourcePermissionCommand struct {
UserID int64
TeamID int64
BuiltinRole string
Permission string
UserID int64 `json:"userId,omitempty"`
TeamID int64 `json:"teamId,omitempty"`
BuiltinRole string `json:"builtInRole,omitempty"`
Permission string `json:"permission"`
}
const (

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