From 3dbcd94d43867072259f08c99814e347540d9f90 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 1 Aug 2022 09:11:56 -0400 Subject: [PATCH 01/30] CloudMonitoring: Remove link setting for SLO queries (#53031) (#53036) (cherry picked from commit 314eb5223f55cf379ca7d9773731837148b613b6) Co-authored-by: Andres Martinez Gotor --- pkg/tsdb/cloudmonitoring/cloudmonitoring.go | 12 +++++++----- pkg/tsdb/cloudmonitoring/time_series_filter_test.go | 13 +++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/tsdb/cloudmonitoring/cloudmonitoring.go b/pkg/tsdb/cloudmonitoring/cloudmonitoring.go index 6f8fbb1cf92..df8679d1dfe 100644 --- a/pkg/tsdb/cloudmonitoring/cloudmonitoring.go +++ b/pkg/tsdb/cloudmonitoring/cloudmonitoring.go @@ -658,12 +658,14 @@ func addConfigData(frames data.Frames, dl string, unit string) data.Frames { if frames[i].Fields[1].Config == nil { frames[i].Fields[1].Config = &data.FieldConfig{} } - deepLink := data.DataLink{ - Title: "View in Metrics Explorer", - TargetBlank: true, - URL: dl, + if len(dl) > 0 { + deepLink := data.DataLink{ + Title: "View in Metrics Explorer", + TargetBlank: true, + URL: dl, + } + frames[i].Fields[1].Config.Links = append(frames[i].Fields[1].Config.Links, deepLink) } - frames[i].Fields[1].Config.Links = append(frames[i].Fields[1].Config.Links, deepLink) if len(unit) > 0 { if val, ok := cloudMonitoringUnitMappings[unit]; ok { frames[i].Fields[1].Config.Unit = val diff --git a/pkg/tsdb/cloudmonitoring/time_series_filter_test.go b/pkg/tsdb/cloudmonitoring/time_series_filter_test.go index 72812087e51..9981b38ed12 100644 --- a/pkg/tsdb/cloudmonitoring/time_series_filter_test.go +++ b/pkg/tsdb/cloudmonitoring/time_series_filter_test.go @@ -459,6 +459,19 @@ func TestTimeSeriesFilter(t *testing.T) { }, *res.Frames[0].Meta) }) }) + + t.Run("when data comes from a slo query, it should skip the link", func(t *testing.T) { + data, err := loadTestFile("./test-data/3-series-response-distribution-exponential.json") + require.NoError(t, err) + assert.Equal(t, 1, len(data.TimeSeries)) + + res := &backend.DataResponse{} + query := &cloudMonitoringTimeSeriesFilter{Params: url.Values{}, Slo: "yes"} + err = query.parseResponse(res, data, "") + require.NoError(t, err) + frames := res.Frames + assert.Equal(t, len(frames[0].Fields[1].Config.Links), 0) + }) } func loadTestFile(path string) (cloudMonitoringResponse, error) { From 1a065b58ce8bee00d2b7e1f78d95363c78fa5090 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 1 Aug 2022 10:41:35 -0400 Subject: [PATCH 02/30] CloudWatch: the variable editor should accept custom values (#52955) (#53045) (cherry picked from commit 74f0c3dbd4d343a8fe294442b7fb3f910b37ea90) Co-authored-by: Isabella Siu --- .../components/VariableQueryEditor/VariableQueryEditor.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx index 80330d06fc4..a7b841cc8fe 100644 --- a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx @@ -122,6 +122,7 @@ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => { onChange={(value: string) => onNamespaceChange(value)} label="Namespace" inputId={`variable-query-namespace-${query.refId}`} + allowCustomValue /> )} {parsedQuery.queryType === VariableQueryType.DimensionValues && ( @@ -132,6 +133,7 @@ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => { onChange={(value: string) => onQueryChange({ ...parsedQuery, metricName: value })} label="Metric" inputId={`variable-query-metric-${query.refId}`} + allowCustomValue /> { onChange={(value: string) => onQueryChange({ ...parsedQuery, dimensionKey: value })} label="Dimension key" inputId={`variable-query-dimension-key-${query.refId}`} + allowCustomValue /> Date: Mon, 1 Aug 2022 11:32:34 -0400 Subject: [PATCH 03/30] TimeSeriesPanel: Tooltip works properly when changing modes (#52876) (#53055) * TimeSeriesPanel: Tooltip works properly when changing modes * TooltipPlugin respects display mode * Pass options to TimeSeriesPanel props (cherry picked from commit 2948bf01dc2d8f31da296d1a805aade94c336ebf) Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com> --- public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx index dfa3861e293..6a2a51409e9 100644 --- a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx +++ b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx @@ -61,6 +61,7 @@ export const TimeSeriesPanel: React.FC = ({ width={width} height={height} legend={options.legend} + options={options} > {(config, alignedDataFrame) => { return ( From 0446c57ec4a28a9e7e5f40f6e6457f7987a5ff51 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 1 Aug 2022 11:40:56 -0400 Subject: [PATCH 04/30] CloudWatch: add CloudWatchSynthetics namespace (#52956) (#53048) (cherry picked from commit 52b57fdb1c2e3eca09c321d96424ebd09049d693) Co-authored-by: Isabella Siu --- pkg/tsdb/cloudwatch/metrics.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/tsdb/cloudwatch/metrics.go b/pkg/tsdb/cloudwatch/metrics.go index 30d5b31b35e..a061799e88d 100644 --- a/pkg/tsdb/cloudwatch/metrics.go +++ b/pkg/tsdb/cloudwatch/metrics.go @@ -398,6 +398,7 @@ var metricsMap = map[string][]string{ "AWS/Rekognition": {"DetectedFaceCount", "DetectedLabelCount", "ResponseTime", "ServerErrorCount", "SuccessfulRequestCount", "ThrottledCount", "UserErrorCount"}, "AWS/Cassandra": {"AccountMaxReads", "AccountMaxTableLevelReads", "AccountMaxTableLevelWrites", "AccountMaxWrites", "AccountProvisionedReadCapacityUtilization", "AccountProvisionedWriteCapacityUtilization", "ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "MaxProvisionedTableReadCapacityUtilization", "MaxProvisionedTableWriteCapacityUtilization", "ReturnedItemCount", "ReturnedItemCountBySelect", "SuccessfulRequestCount", "SuccessfulRequestLatency", "SystemErrors", "UserErrors"}, "AWS/AmplifyHosting": {"Requests", "BytesDownloaded", "BytesUploaded", "4XXErrors", "5XXErrors", "Latency"}, + "CloudWatchSynthetics": {"SuccessPercent", "Duration", "2xx", "4xx", "5xx", "Failed", "Failed requests", "VisualMonitoringSuccessPercent", "VisualMonitoringTotalComparisons"}, } var dimensionsMap = map[string][]string{ @@ -513,6 +514,7 @@ var dimensionsMap = map[string][]string{ "AWS/Rekognition": {}, "AWS/Cassandra": {"Keyspace", "Operation", "TableName"}, "AWS/AmplifyHosting": {"App"}, + "CloudWatchSynthetics": {"CanaryName"}, } // Known AWS regions. From 5cfda094c6f25f1f447a0aa634603414791d4b59 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 2 Aug 2022 09:10:18 +0100 Subject: [PATCH 05/30] "Release: Updated versions in package to 9.0.6" (#53091) --- lerna.json | 2 +- package.json | 2 +- packages/grafana-data/package.json | 4 +- packages/grafana-e2e-selectors/package.json | 2 +- packages/grafana-e2e/package.json | 4 +- packages/grafana-runtime/package.json | 8 ++-- packages/grafana-schema/package.json | 2 +- packages/grafana-toolkit/package.json | 6 +-- packages/grafana-ui/package.json | 8 ++-- packages/jaeger-ui-components/package.json | 10 ++-- .../internal/input-datasource/package.json | 8 ++-- yarn.lock | 46 +++++++++---------- 12 files changed, 51 insertions(+), 51 deletions(-) diff --git a/lerna.json b/lerna.json index 89ce6b595f4..afefc2c8716 100644 --- a/lerna.json +++ b/lerna.json @@ -4,5 +4,5 @@ "packages": [ "packages/*" ], - "version": "9.0.5" + "version": "9.0.6" } diff --git a/package.json b/package.json index 91332f36811..b0f9961e9f6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "grafana", - "version": "9.0.5", + "version": "9.0.6", "repository": "github:grafana/grafana", "scripts": { "api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index d5e2d14781a..5bf982874ec 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/data", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana Data Library", "keywords": [ "typescript" @@ -22,7 +22,7 @@ }, "dependencies": { "@braintree/sanitize-url": "6.0.0", - "@grafana/schema": "9.0.5", + "@grafana/schema": "9.0.6", "@types/d3-interpolate": "^1.4.0", "d3-interpolate": "1.4.0", "date-fns": "2.28.0", diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 905a77f13ac..c1ea8c6e688 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e-selectors", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana End-to-End Test Selectors Library", "keywords": [ "cli", diff --git a/packages/grafana-e2e/package.json b/packages/grafana-e2e/package.json index 5830966d431..163f0acf9c4 100644 --- a/packages/grafana-e2e/package.json +++ b/packages/grafana-e2e/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana End-to-End Test Library", "keywords": [ "cli", @@ -48,7 +48,7 @@ "@babel/core": "7.17.8", "@babel/preset-env": "7.17.10", "@cypress/webpack-preprocessor": "5.11.1", - "@grafana/e2e-selectors": "9.0.5", + "@grafana/e2e-selectors": "9.0.6", "@grafana/tsconfig": "^1.2.0-rc1", "@mochajs/json-file-reporter": "^1.2.0", "babel-loader": "8.2.5", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 5c823c6a14a..673ebb5cdc3 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/runtime", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana Runtime Library", "keywords": [ "grafana", @@ -22,9 +22,9 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@grafana/data": "9.0.5", - "@grafana/e2e-selectors": "9.0.5", - "@grafana/ui": "9.0.5", + "@grafana/data": "9.0.6", + "@grafana/e2e-selectors": "9.0.6", + "@grafana/ui": "9.0.6", "@sentry/browser": "6.19.7", "history": "4.10.1", "lodash": "4.17.21", diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 9176832f07f..621108dc1ca 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/schema", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana Schema Library", "keywords": [ "typescript" diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index a5d6720066c..9673d3aa291 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/toolkit", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana Toolkit", "keywords": [ "grafana", @@ -38,10 +38,10 @@ "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.16.7", - "@grafana/data": "9.0.5", + "@grafana/data": "9.0.6", "@grafana/eslint-config": "^4.0.0", "@grafana/tsconfig": "^1.2.0-rc1", - "@grafana/ui": "9.0.5", + "@grafana/ui": "9.0.6", "@jest/core": "27.5.1", "@types/command-exists": "^1.2.0", "@types/eslint": "8.4.1", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index afe2b540ba1..962e7976c1b 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/ui", - "version": "9.0.5", + "version": "9.0.6", "description": "Grafana Components Library", "keywords": [ "grafana", @@ -33,9 +33,9 @@ "@emotion/css": "11.9.0", "@emotion/react": "11.9.0", "@grafana/aws-sdk": "0.0.36", - "@grafana/data": "9.0.5", - "@grafana/e2e-selectors": "9.0.5", - "@grafana/schema": "9.0.5", + "@grafana/data": "9.0.6", + "@grafana/e2e-selectors": "9.0.6", + "@grafana/schema": "9.0.6", "@grafana/slate-react": "0.22.10-grafana", "@monaco-editor/react": "4.3.1", "@popperjs/core": "2.11.5", diff --git a/packages/jaeger-ui-components/package.json b/packages/jaeger-ui-components/package.json index ba21da3c431..fbab5158cbc 100644 --- a/packages/jaeger-ui-components/package.json +++ b/packages/jaeger-ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@jaegertracing/jaeger-ui-components", - "version": "9.0.5", + "version": "9.0.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,10 +28,10 @@ }, "dependencies": { "@emotion/css": "11.9.0", - "@grafana/data": "9.0.5", - "@grafana/e2e-selectors": "9.0.5", - "@grafana/runtime": "9.0.5", - "@grafana/ui": "9.0.5", + "@grafana/data": "9.0.6", + "@grafana/e2e-selectors": "9.0.6", + "@grafana/runtime": "9.0.6", + "@grafana/ui": "9.0.6", "chance": "^1.0.10", "classnames": "^2.2.5", "combokeys": "^3.0.0", diff --git a/plugins-bundled/internal/input-datasource/package.json b/plugins-bundled/internal/input-datasource/package.json index 9d846d31df1..88d6a51fe5c 100644 --- a/plugins-bundled/internal/input-datasource/package.json +++ b/plugins-bundled/internal/input-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@grafana-plugins/input-datasource", - "version": "9.0.5", + "version": "9.0.6", "description": "Input Datasource", "private": true, "repository": { @@ -15,15 +15,15 @@ }, "author": "Grafana Labs", "devDependencies": { - "@grafana/toolkit": "9.0.5", + "@grafana/toolkit": "9.0.6", "@types/jest": "26.0.15", "@types/lodash": "4.14.149", "@types/react": "17.0.30", "lodash": "4.17.21" }, "dependencies": { - "@grafana/data": "9.0.5", - "@grafana/ui": "9.0.5", + "@grafana/data": "9.0.6", + "@grafana/ui": "9.0.6", "jquery": "3.5.1", "react": "17.0.1", "react-dom": "17.0.1", diff --git a/yarn.lock b/yarn.lock index 21b4fcd7789..31c3d47cd50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3791,9 +3791,9 @@ __metadata: version: 0.0.0-use.local resolution: "@grafana-plugins/input-datasource@workspace:plugins-bundled/internal/input-datasource" dependencies: - "@grafana/data": 9.0.5 - "@grafana/toolkit": 9.0.5 - "@grafana/ui": 9.0.5 + "@grafana/data": 9.0.6 + "@grafana/toolkit": 9.0.6 + "@grafana/ui": 9.0.6 "@types/jest": 26.0.15 "@types/lodash": 4.14.149 "@types/react": 17.0.30 @@ -3831,12 +3831,12 @@ __metadata: languageName: node linkType: hard -"@grafana/data@9.0.5, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": +"@grafana/data@9.0.6, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": version: 0.0.0-use.local resolution: "@grafana/data@workspace:packages/grafana-data" dependencies: "@braintree/sanitize-url": 6.0.0 - "@grafana/schema": 9.0.5 + "@grafana/schema": 9.0.6 "@grafana/tsconfig": ^1.2.0-rc1 "@rollup/plugin-commonjs": 22.0.0 "@rollup/plugin-json": 4.1.0 @@ -3889,7 +3889,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/e2e-selectors@9.0.5, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": +"@grafana/e2e-selectors@9.0.6, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": version: 0.0.0-use.local resolution: "@grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors" dependencies: @@ -3913,7 +3913,7 @@ __metadata: "@babel/core": 7.17.8 "@babel/preset-env": 7.17.10 "@cypress/webpack-preprocessor": 5.11.1 - "@grafana/e2e-selectors": 9.0.5 + "@grafana/e2e-selectors": 9.0.6 "@grafana/tsconfig": ^1.2.0-rc1 "@mochajs/json-file-reporter": ^1.2.0 "@rollup/plugin-commonjs": 22.0.0 @@ -3998,14 +3998,14 @@ __metadata: languageName: node linkType: hard -"@grafana/runtime@9.0.5, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": +"@grafana/runtime@9.0.6, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": version: 0.0.0-use.local resolution: "@grafana/runtime@workspace:packages/grafana-runtime" dependencies: - "@grafana/data": 9.0.5 - "@grafana/e2e-selectors": 9.0.5 + "@grafana/data": 9.0.6 + "@grafana/e2e-selectors": 9.0.6 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.0.5 + "@grafana/ui": 9.0.6 "@rollup/plugin-commonjs": 22.0.0 "@rollup/plugin-node-resolve": 13.3.0 "@sentry/browser": 6.19.7 @@ -4034,7 +4034,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/schema@9.0.5, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": +"@grafana/schema@9.0.6, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": version: 0.0.0-use.local resolution: "@grafana/schema@workspace:packages/grafana-schema" dependencies: @@ -4081,7 +4081,7 @@ __metadata: languageName: node linkType: hard -"@grafana/toolkit@9.0.5, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit": +"@grafana/toolkit@9.0.6, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit": version: 0.0.0-use.local resolution: "@grafana/toolkit@workspace:packages/grafana-toolkit" dependencies: @@ -4097,10 +4097,10 @@ __metadata: "@babel/preset-env": ^7.16.11 "@babel/preset-react": ^7.16.7 "@babel/preset-typescript": ^7.16.7 - "@grafana/data": 9.0.5 + "@grafana/data": 9.0.6 "@grafana/eslint-config": ^4.0.0 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.0.5 + "@grafana/ui": 9.0.6 "@jest/core": 27.5.1 "@types/command-exists": ^1.2.0 "@types/eslint": 8.4.1 @@ -4184,7 +4184,7 @@ __metadata: languageName: node linkType: hard -"@grafana/ui@9.0.5, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": +"@grafana/ui@9.0.6, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": version: 0.0.0-use.local resolution: "@grafana/ui@workspace:packages/grafana-ui" dependencies: @@ -4192,9 +4192,9 @@ __metadata: "@emotion/css": 11.9.0 "@emotion/react": 11.9.0 "@grafana/aws-sdk": 0.0.36 - "@grafana/data": 9.0.5 - "@grafana/e2e-selectors": 9.0.5 - "@grafana/schema": 9.0.5 + "@grafana/data": 9.0.6 + "@grafana/e2e-selectors": 9.0.6 + "@grafana/schema": 9.0.6 "@grafana/slate-react": 0.22.10-grafana "@grafana/tsconfig": ^1.2.0-rc1 "@mdx-js/react": 1.6.22 @@ -4431,11 +4431,11 @@ __metadata: resolution: "@jaegertracing/jaeger-ui-components@workspace:packages/jaeger-ui-components" dependencies: "@emotion/css": 11.9.0 - "@grafana/data": 9.0.5 - "@grafana/e2e-selectors": 9.0.5 - "@grafana/runtime": 9.0.5 + "@grafana/data": 9.0.6 + "@grafana/e2e-selectors": 9.0.6 + "@grafana/runtime": 9.0.6 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.0.5 + "@grafana/ui": 9.0.6 "@testing-library/react": 12.1.4 "@testing-library/user-event": 14.2.0 "@types/classnames": ^2.2.7 From 7ac8049376d4109e2101551b229d00bdbaee2b23 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 2 Aug 2022 09:28:23 +0100 Subject: [PATCH 06/30] ReleaseNotes: Updated changelog and release notes for 9.0.6 (#53092) (#53093) (cherry picked from commit 47a7f84c86b31407bc2d5551c756dceb6cbe2077) --- CHANGELOG.md | 15 +++++++++++++++ docs/sources/release-notes/_index.md | 1 + .../release-notes/release-notes-9-0-6.md | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 docs/sources/release-notes/release-notes-9-0-6.md diff --git a/CHANGELOG.md b/CHANGELOG.md index a9ef3115678..85a4cbfb5c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ + + +# 9.0.6 (2022-08-01) + +### Features and enhancements + +- **Access Control:** Allow org admins to invite new users to their organization. [#52904](https://github.com/grafana/grafana/pull/52904), [@IevaVasiljeva](https://github.com/IevaVasiljeva) + +### Bug fixes + +- **Grafana/toolkit:** Fix incorrect image and font generation for plugin builds. [#52927](https://github.com/grafana/grafana/pull/52927), [@academo](https://github.com/academo) +- **Prometheus:** Fix adding of multiple values for regex operator. [#52978](https://github.com/grafana/grafana/pull/52978), [@ivanahuckova](https://github.com/ivanahuckova) +- **UI/Card:** Fix card items always having pointer cursor. [#52809](https://github.com/grafana/grafana/pull/52809), [@gillesdemey](https://github.com/gillesdemey) + + # 9.0.5 (2022-07-26) diff --git a/docs/sources/release-notes/_index.md b/docs/sources/release-notes/_index.md index 796d7d6009e..b181446fe9e 100644 --- a/docs/sources/release-notes/_index.md +++ b/docs/sources/release-notes/_index.md @@ -10,6 +10,7 @@ weight: 10000 Here you can find detailed release notes that list everything that is included in every release as well as notices about deprecations, breaking changes as well as changes that relate to plugin development. +- [Release notes for 9.0.6]({{< relref "release-notes-9-0-6" >}}) - [Release notes for 9.0.5]({{< relref "release-notes-9-0-5" >}}) - [Release notes for 9.0.4]({{< relref "release-notes-9-0-4" >}}) - [Release notes for 9.0.3]({{< relref "release-notes-9-0-3" >}}) diff --git a/docs/sources/release-notes/release-notes-9-0-6.md b/docs/sources/release-notes/release-notes-9-0-6.md new file mode 100644 index 00000000000..3d7f470aa5d --- /dev/null +++ b/docs/sources/release-notes/release-notes-9-0-6.md @@ -0,0 +1,18 @@ ++++ +title = "Release notes for Grafana 9.0.6" +hide_menu = true ++++ + + + +# Release notes for Grafana 9.0.6 + +### Features and enhancements + +- **Access Control:** Allow org admins to invite new users to their organization. [#52904](https://github.com/grafana/grafana/pull/52904), [@IevaVasiljeva](https://github.com/IevaVasiljeva) + +### Bug fixes + +- **Grafana/toolkit:** Fix incorrect image and font generation for plugin builds. [#52927](https://github.com/grafana/grafana/pull/52927), [@academo](https://github.com/academo) +- **Prometheus:** Fix adding of multiple values for regex operator. [#52978](https://github.com/grafana/grafana/pull/52978), [@ivanahuckova](https://github.com/ivanahuckova) +- **UI/Card:** Fix card items always having pointer cursor. [#52809](https://github.com/grafana/grafana/pull/52809), [@gillesdemey](https://github.com/gillesdemey) From ea938c9962f1632f13d677d28258ea04f8ddcff7 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 2 Aug 2022 15:10:45 +0100 Subject: [PATCH 07/30] Azure Monitor: Clarify removed query methods (#52986) (#53142) (cherry picked from commit 194d0fe33b67cd5b19859f15ffdc03b3a478525a) Co-authored-by: Andres Martinez Gotor --- .../azuremonitor/deprecated-application-insights.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/sources/datasources/azuremonitor/deprecated-application-insights.md b/docs/sources/datasources/azuremonitor/deprecated-application-insights.md index 68c836a83af..f81ee4f8d89 100644 --- a/docs/sources/datasources/azuremonitor/deprecated-application-insights.md +++ b/docs/sources/datasources/azuremonitor/deprecated-application-insights.md @@ -18,7 +18,9 @@ weight: 999 # Deprecated Application Insights and Insights Analytics -Application Insights and Insights Analytics are two ways to query the same Azure Application Insights data, which can also be queried from Metrics and Logs. In Grafana 8.0, Application Insights and Insights Analytics are deprecated and made read-only in favor of querying this data through Metrics and Logs. Existing queries will continue to work, but you cannot edit them. New panels are not able to use Application Insights or Insights Analytics. +Application Insights and Insights Analytics are two ways to query the same Azure Application Insights data, which can also be queried from Metrics and Logs. In Grafana 8.0, Application Insights and Insights Analytics were deprecated and made read-only in favor of querying this data through Metrics and Logs. + +These query methods were completely removed in Grafana 9.0. Azure Monitor Metrics and Azure Monitor Logs do not use Application Insights API keys, so make sure the data source is configured with an Azure AD app registration that has access to Application Insights. From a010d126844a0440210c18a18b34d2d68fb6560b Mon Sep 17 00:00:00 2001 From: Yuriy Tseretyan Date: Tue, 2 Aug 2022 12:31:42 -0400 Subject: [PATCH 08/30] [9.0.x] Alerting: Remove user input from error response (#53158) * omit recipient input from the error Co-authored-by: Alexander Weaver --- pkg/services/ngalert/api/util.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/services/ngalert/api/util.go b/pkg/services/ngalert/api/util.go index 6654ba21485..41cc56c4b91 100644 --- a/pkg/services/ngalert/api/util.go +++ b/pkg/services/ngalert/api/util.go @@ -25,7 +25,7 @@ import ( ) var searchRegex = regexp.MustCompile(`\{(\w+)\}`) - +var errInvalidRecipientFormat = errors.New("invalid recipient (datasource) identifier format. Only integer is expected") var NotImplementedResp = ErrResp(http.StatusNotImplemented, errors.New("endpoint not implemented"), "") func toMacaronPath(path string) string { @@ -37,7 +37,8 @@ func toMacaronPath(path string) string { func backendTypeByUID(ctx *models.ReqContext, cache datasources.CacheService) (apimodels.Backend, error) { datasourceUID := web.Params(ctx.Req)[":DatasourceUID"] - if ds, err := cache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipCache); err == nil { + ds, err := cache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipCache) + if err == nil { switch ds.Type { case "loki", "prometheus": return apimodels.LoTexRulerBackend, nil @@ -47,7 +48,7 @@ func backendTypeByUID(ctx *models.ReqContext, cache datasources.CacheService) (a return 0, fmt.Errorf("unexpected backend type (%v)", ds.Type) } } - return 0, fmt.Errorf("unexpected backend type (%v)", datasourceUID) + return 0, errors.New("no datasource was found matching the given UID") } // macaron unsafely asserts the http.ResponseWriter is an http.CloseNotifier, which will panic. @@ -100,7 +101,7 @@ func (p *AlertingProxy) withReq( if datasourceID != "" { recipient, err := strconv.ParseInt(web.Params(ctx.Req)[":DatasourceID"], 10, 64) if err != nil { - return ErrResp(http.StatusBadRequest, err, "DatasourceID is invalid") + return ErrResp(http.StatusBadRequest, errInvalidRecipientFormat, "") } p.DataProxy.ProxyDatasourceRequestWithID(newCtx, recipient) From f1b5f233b468216f0fdeca5043e9f52ca66fb56d Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 3 Aug 2022 14:11:07 +0100 Subject: [PATCH 09/30] RolePicker: Fix RolePicker menu positioning (#53201) (#53215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #52800 (cherry picked from commit dc775c7577501088ed929a6c6d986a05c05d0028) Co-authored-by: Mihály Gyöngyösi --- public/app/core/components/RolePicker/RolePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/components/RolePicker/RolePicker.tsx b/public/app/core/components/RolePicker/RolePicker.tsx index e850cf1a355..c3fff8a8e57 100644 --- a/public/app/core/components/RolePicker/RolePicker.tsx +++ b/public/app/core/components/RolePicker/RolePicker.tsx @@ -131,7 +131,7 @@ export const RolePicker = ({ } return ( -
+
Date: Wed, 3 Aug 2022 14:59:05 +0100 Subject: [PATCH 10/30] Plugins: Validate root URLs when signing private plugins via grafana-toolkit (#51968) (#53228) * validate URLs * apply PR review feedback * fix err msg (cherry picked from commit b32ad993c504b72ae912683b5512e3fe7c3cabf9) Co-authored-by: Will Browne --- packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts | 3 ++- packages/grafana-toolkit/src/cli/tasks/plugin.sign.ts | 2 ++ .../grafana-toolkit/src/config/utils/pluginValidation.ts | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts index 40d8eb0072f..cfd04176656 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts @@ -5,7 +5,7 @@ import rimrafCallback from 'rimraf'; import { promisify } from 'util'; import { getPluginId } from '../../config/utils/getPluginId'; -import { getPluginJson } from '../../config/utils/pluginValidation'; +import { assertRootUrlIsValid, getPluginJson } from '../../config/utils/pluginValidation'; import { getJobFolder, writeJobStats, @@ -141,6 +141,7 @@ const packagePluginRunner: TaskRunner = async ({ signatureType, manifest.signatureType = signatureType; } if (rootUrls) { + rootUrls.forEach(assertRootUrlIsValid); manifest.rootUrls = rootUrls; } const signedManifest = await signManifest(manifest); diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.sign.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.sign.ts index 7424bdeb1fb..064e53eb445 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.sign.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.sign.ts @@ -1,5 +1,6 @@ import path from 'path'; +import { assertRootUrlIsValid } from '../../config/utils/pluginValidation'; import { buildManifest, signManifest, saveManifest } from '../../plugins/manifest'; import { getToolkitVersion } from './plugin.utils'; @@ -22,6 +23,7 @@ const pluginSignRunner: TaskRunner = async ({ signatureType, manifest.signatureType = signatureType; } if (rootUrls) { + rootUrls.forEach(assertRootUrlIsValid); manifest.rootUrls = rootUrls; } diff --git a/packages/grafana-toolkit/src/config/utils/pluginValidation.ts b/packages/grafana-toolkit/src/config/utils/pluginValidation.ts index f2ff2cdf7df..80b88ce8f13 100644 --- a/packages/grafana-toolkit/src/config/utils/pluginValidation.ts +++ b/packages/grafana-toolkit/src/config/utils/pluginValidation.ts @@ -36,3 +36,11 @@ export const getPluginJson = (path: string): PluginMeta => { return pluginJson as PluginMeta; }; + +export const assertRootUrlIsValid = (rootUrl: string) => { + try { + new URL(rootUrl); + } catch (err) { + throw new Error(`${rootUrl} is not a valid URL`); + } +}; From a8b9d8037a3f683d62fb51ab0144a0189a119f1a Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:33:29 +0100 Subject: [PATCH 11/30] add missing check for root URLs length (#53239) (#53250) (cherry picked from commit 46b7ca12e1ae19f91d6dfd79c9b2f8cf5b7603c3) Co-authored-by: Will Browne --- packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts index cfd04176656..53078e4185e 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts @@ -140,7 +140,7 @@ const packagePluginRunner: TaskRunner = async ({ signatureType, if (signatureType) { manifest.signatureType = signatureType; } - if (rootUrls) { + if (rootUrls && rootUrls.length > 0) { rootUrls.forEach(assertRootUrlIsValid); manifest.rootUrls = rootUrls; } From 68782b12de8e3ff1d74174d0ca7af7403eb15bdf Mon Sep 17 00:00:00 2001 From: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:34:04 -0700 Subject: [PATCH 12/30] Geomap: Fix tooltip offset bug (#53274) --- public/app/plugins/panel/geomap/GeomapPanel.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/geomap/GeomapPanel.tsx b/public/app/plugins/panel/geomap/GeomapPanel.tsx index c1e53aff71b..8b23a733452 100644 --- a/public/app/plugins/panel/geomap/GeomapPanel.tsx +++ b/public/app/plugins/panel/geomap/GeomapPanel.tsx @@ -355,8 +355,8 @@ export class GeomapPanel extends Component { const hover = toLonLat(this.map.getCoordinateFromPixel(pixel)); const { hoverPayload } = this; - hoverPayload.pageX = mouse.pageX; - hoverPayload.pageY = mouse.pageY; + hoverPayload.pageX = mouse.offsetX; + hoverPayload.pageY = mouse.offsetY; hoverPayload.point = { lat: hover[1], lon: hover[0], From 27c1d18208cc70248545e085a61fa4e754c776c9 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Thu, 4 Aug 2022 12:38:45 +0100 Subject: [PATCH 13/30] GrafanaUI: Render PageToolbar's leftItems regardless of title's presence (#53285) (#53291) * Grafana-UI: make PageToolbar render leftItems regardless of title's presence * simplify test (cherry picked from commit 1ec9007fe073052b37890e6804d8d9313e66e029) Co-authored-by: Giordano Ricci --- .../PageLayout/PageToolbar.test.tsx | 13 ++++++ .../src/components/PageLayout/PageToolbar.tsx | 43 ++++++++++--------- 2 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx new file mode 100644 index 00000000000..6fa71287d09 --- /dev/null +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.test.tsx @@ -0,0 +1,13 @@ +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { PageToolbar } from '..'; + +describe('PageToolbar', () => { + it('renders left items when title is not set', () => { + const leftItemContent = 'Left Item!'; + render({leftItemContent}
]} />); + + expect(screen.getByText(leftItemContent)).toBeInTheDocument(); + }); +}); diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx index 2af2412a28a..34298aebbd6 100644 --- a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx @@ -61,12 +61,6 @@ export const PageToolbar: FC = React.memo( className ); - const leftItemChildren = leftItems?.map((child, index) => ( -
- {child} -
- )); - const titleEl = ( <> {title} @@ -112,22 +106,29 @@ export const PageToolbar: FC = React.memo( )} - {title && ( + {(title || leftItems?.length) && (
-

- {titleHref ? ( - - {titleEl} - - ) : ( -
{titleEl}
- )} -

- {leftItemChildren} + {title && ( +

+ {titleHref ? ( + + {titleEl} + + ) : ( +
{titleEl}
+ )} +

+ )} + + {leftItems?.map((child, index) => ( +
+ {child} +
+ ))}
)} From 1be924fa23cb5520aeadadfd7fedab4f09089f66 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> Date: Thu, 4 Aug 2022 19:24:12 +0300 Subject: [PATCH 14/30] [v9.0.x] API: Fix snapshot responses (#53312) * API: Fix snapshot responses (#52998) * API: Fix response status when snapshots are not found * API: Fix response status when snapshot key is empty * Apply suggestions from code review (cherry picked from commit 5fec6cc4f5b7dd4aa37399e93a77e6111d867f95) --- pkg/api/dashboard_snapshot.go | 17 +++++-- pkg/api/dashboard_snapshot_test.go | 69 ++++++++++++++++++++++++++++ pkg/api/docs/definitions/snapshot.go | 1 + public/api-merged.json | 3 ++ public/api-spec.json | 3 ++ 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/pkg/api/dashboard_snapshot.go b/pkg/api/dashboard_snapshot.go index 53c3cebed62..c023a669c4f 100644 --- a/pkg/api/dashboard_snapshot.go +++ b/pkg/api/dashboard_snapshot.go @@ -153,14 +153,17 @@ func (hs *HTTPServer) CreateDashboardSnapshot(c *models.ReqContext) response.Res func (hs *HTTPServer) GetDashboardSnapshot(c *models.ReqContext) response.Response { key := web.Params(c.Req)[":key"] if len(key) == 0 { - return response.Error(404, "Snapshot not found", nil) + return response.Error(http.StatusBadRequest, "Empty snapshot key", nil) } query := &models.GetDashboardSnapshotQuery{Key: key} err := hs.DashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { - return response.Error(500, "Failed to get dashboard snapshot", err) + if errors.Is(err, models.ErrDashboardSnapshotNotFound) { + return response.Error(http.StatusNotFound, "Failed to find dashboard snapshot", err) + } + return response.Error(http.StatusInternalServerError, "Failed to get dashboard snapshot", err) } snapshot := query.Result @@ -227,7 +230,10 @@ func (hs *HTTPServer) DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) r query := &models.GetDashboardSnapshotQuery{DeleteKey: key} err := hs.DashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { - return response.Error(500, "Failed to get dashboard snapshot", err) + if errors.Is(err, models.ErrDashboardSnapshotNotFound) { + return response.Error(http.StatusNotFound, "Failed to find dashboard snapshot", err) + } + return response.Error(http.StatusInternalServerError, "Failed to get dashboard snapshot", err) } if query.Result.External { @@ -260,7 +266,10 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res err := hs.DashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { - return response.Error(500, "Failed to get dashboard snapshot", err) + if errors.Is(err, models.ErrDashboardSnapshotNotFound) { + return response.Error(http.StatusNotFound, "Failed to find dashboard snapshot", err) + } + return response.Error(http.StatusInternalServerError, "Failed to get dashboard snapshot", err) } if query.Result == nil { return response.Error(404, "Failed to get dashboard snapshot", nil) diff --git a/pkg/api/dashboard_snapshot_test.go b/pkg/api/dashboard_snapshot_test.go index cdab0462bb5..5f5c209d483 100644 --- a/pkg/api/dashboard_snapshot_test.go +++ b/pkg/api/dashboard_snapshot_test.go @@ -1,6 +1,7 @@ package api import ( + "errors" "fmt" "net/http" "net/http/httptest" @@ -229,3 +230,71 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { }, sqlmock) }) } + +func TestGetDashboardSnapshotNotFound(t *testing.T) { + sqlmock := mockstore.NewSQLStoreMock() + sqlmock.ExpectedTeamsByUser = []*models.TeamDTO{} + sqlmock.ExpectedError = models.ErrDashboardSnapshotNotFound + hs := &HTTPServer{DashboardsnapshotsService: &dashboardsnapshots.Service{SQLStore: sqlmock}} + + loggedInUserScenarioWithRole(t, + "GET /snapshots/{key} should return 404 when the snapshot does not exist", "GET", + "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.GetDashboardSnapshot + sc.fakeReqWithParams("GET", sc.url, map[string]string{"key": "12345"}).exec() + + assert.Equal(t, http.StatusNotFound, sc.resp.Code) + }, sqlmock) + + loggedInUserScenarioWithRole(t, + "DELETE /snapshots/{key} should return 404 when the snapshot does not exist", "DELETE", + "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.DeleteDashboardSnapshot + sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() + + assert.Equal(t, http.StatusNotFound, sc.resp.Code) + }, sqlmock) + + loggedInUserScenarioWithRole(t, + "GET /snapshots-delete/{deleteKey} should return 404 when the snapshot does not exist", "DELETE", + "/api/snapshots-delete/12345", "/api/snapshots-delete/:deleteKey", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.DeleteDashboardSnapshotByDeleteKey + sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"deleteKey": "12345"}).exec() + + assert.Equal(t, http.StatusNotFound, sc.resp.Code) + }, sqlmock) +} + +func TestGetDashboardSnapshotFailure(t *testing.T) { + sqlmock := mockstore.NewSQLStoreMock() + sqlmock.ExpectedTeamsByUser = []*models.TeamDTO{} + sqlmock.ExpectedError = errors.New("something went wrong") + hs := &HTTPServer{DashboardsnapshotsService: &dashboardsnapshots.Service{SQLStore: sqlmock}} + + loggedInUserScenarioWithRole(t, + "GET /snapshots/{key} should return 404 when the snapshot does not exist", "GET", + "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.GetDashboardSnapshot + sc.fakeReqWithParams("GET", sc.url, map[string]string{"key": "12345"}).exec() + + assert.Equal(t, http.StatusInternalServerError, sc.resp.Code) + }, sqlmock) + + loggedInUserScenarioWithRole(t, + "DELETE /snapshots/{key} should return 404 when the snapshot does not exist", "DELETE", + "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.DeleteDashboardSnapshot + sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() + + assert.Equal(t, http.StatusInternalServerError, sc.resp.Code) + }, sqlmock) + + loggedInUserScenarioWithRole(t, + "GET /snapshots-delete/{deleteKey} should return 404 when the snapshot does not exist", "DELETE", + "/api/snapshots-delete/12345", "/api/snapshots-delete/:deleteKey", models.ROLE_EDITOR, func(sc *scenarioContext) { + sc.handlerFunc = hs.DeleteDashboardSnapshotByDeleteKey + sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"deleteKey": "12345"}).exec() + + assert.Equal(t, http.StatusInternalServerError, sc.resp.Code) + }, sqlmock) +} diff --git a/pkg/api/docs/definitions/snapshot.go b/pkg/api/docs/definitions/snapshot.go index 4926595a722..c1549ccefd9 100644 --- a/pkg/api/docs/definitions/snapshot.go +++ b/pkg/api/docs/definitions/snapshot.go @@ -30,6 +30,7 @@ import ( // // Responses: // 200: snapshotResponse +// 400: badRequestError // 404: notFoundError // 500: internalServerError diff --git a/public/api-merged.json b/public/api-merged.json index 269c5a11e88..90900c0e2b1 100644 --- a/public/api-merged.json +++ b/public/api-merged.json @@ -6898,6 +6898,9 @@ "200": { "$ref": "#/responses/snapshotResponse" }, + "400": { + "$ref": "#/responses/badRequestError" + }, "404": { "$ref": "#/responses/notFoundError" }, diff --git a/public/api-spec.json b/public/api-spec.json index a42630925d2..453591541df 100644 --- a/public/api-spec.json +++ b/public/api-spec.json @@ -6898,6 +6898,9 @@ "200": { "$ref": "#/responses/snapshotResponse" }, + "400": { + "$ref": "#/responses/badRequestError" + }, "404": { "$ref": "#/responses/notFoundError" }, From e186375a17a228d512b3c88214ef8e02d16dcdd3 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Fri, 5 Aug 2022 13:51:39 +0100 Subject: [PATCH 15/30] Alerting: Remove mention of host name from Alerting HA docs (#53178) (#53344) (cherry picked from commit 4090e122f81c380eccb020c399a2436c47a42547) Co-authored-by: Yuriy Tseretyan --- docs/sources/setup-grafana/configure-grafana/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index a871ce5ca14..dc425e2b6e6 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -1204,11 +1204,11 @@ The interval string is a possibly signed sequence of decimal numbers, followed b ### ha_listen_address -Listen address/hostname and port to receive unified alerting messages for other Grafana instances. The port is used for both TCP and UDP. It is assumed other Grafana instances are also running on the same port. The default value is `0.0.0.0:9094`. +Listen IP address and port to receive unified alerting messages for other Grafana instances. The port is used for both TCP and UDP. It is assumed other Grafana instances are also running on the same port. The default value is `0.0.0.0:9094`. ### ha_advertise_address -Explicit address/hostname and port to advertise other Grafana instances. The port is used for both TCP and UDP. +Explicit IP address and port to advertise other Grafana instances. The port is used for both TCP and UDP. ### ha_peers From 8ef9ad063b48efc516b319567574dedb912d99e2 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Fri, 5 Aug 2022 19:36:06 +0100 Subject: [PATCH 16/30] Geomap: Do not show markers with empty coordinates (#53330) (#53333) Co-authored-by: nmarrs (cherry picked from commit 64721bfa94dbbc045f2625d6b9af3a57e278e45b) Co-authored-by: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> --- .betterer.results | 21 ++++++++++++++++----- public/app/features/geo/format/utils.ts | 11 ++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/.betterer.results b/.betterer.results index 584acbcd0f1..21e4fe26dc3 100644 --- a/.betterer.results +++ b/.betterer.results @@ -4849,7 +4849,8 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "24"], [0, 0, 0, "Do not use any type assertions.", "25"], [0, 0, 0, "Unexpected any. Specify a different type.", "26"], - [0, 0, 0, "Unexpected any. Specify a different type.", "27"] + [0, 0, 0, "Unexpected any. Specify a different type.", "27"], + [0, 0, 0, "Unexpected any. Specify a different type.", "28"] ], "public/app/features/dashboard/state/TimeModel.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], @@ -6229,9 +6230,6 @@ exports[`better eslint`] = { "public/app/features/transformers/utils.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], - "public/app/features/users/UsersActionBar.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], "public/app/features/users/__mocks__/userMocks.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], @@ -7861,7 +7859,20 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "10"], [0, 0, 0, "Unexpected any. Specify a different type.", "11"], [0, 0, 0, "Unexpected any. Specify a different type.", "12"], - [0, 0, 0, "Unexpected any. Specify a different type.", "13"] + [0, 0, 0, "Unexpected any. Specify a different type.", "13"], + [0, 0, 0, "Unexpected any. Specify a different type.", "14"], + [0, 0, 0, "Unexpected any. Specify a different type.", "15"], + [0, 0, 0, "Unexpected any. Specify a different type.", "16"], + [0, 0, 0, "Unexpected any. Specify a different type.", "17"], + [0, 0, 0, "Unexpected any. Specify a different type.", "18"], + [0, 0, 0, "Unexpected any. Specify a different type.", "19"], + [0, 0, 0, "Unexpected any. Specify a different type.", "20"], + [0, 0, 0, "Unexpected any. Specify a different type.", "21"], + [0, 0, 0, "Unexpected any. Specify a different type.", "22"], + [0, 0, 0, "Unexpected any. Specify a different type.", "23"], + [0, 0, 0, "Unexpected any. Specify a different type.", "24"], + [0, 0, 0, "Unexpected any. Specify a different type.", "25"], + [0, 0, 0, "Unexpected any. Specify a different type.", "26"] ], "public/app/plugins/datasource/loki/datasource.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], diff --git a/public/app/features/geo/format/utils.ts b/public/app/features/geo/format/utils.ts index babba1cde80..c5d5814894d 100644 --- a/public/app/features/geo/format/utils.ts +++ b/public/app/features/geo/format/utils.ts @@ -28,7 +28,16 @@ export function pointFieldFromGeohash(geohash: Field): Field { export function pointFieldFromLonLat(lon: Field, lat: Field): Field { const buffer = new Array(lon.values.length); for (let i = 0; i < lon.values.length; i++) { - buffer[i] = new Point(fromLonLat([lon.values.get(i), lat.values.get(i)])); + const longitude = lon.values.get(i); + const latitude = lat.values.get(i); + + // TODO: Add unit tests to thoroughly test out edge cases + // If longitude or latitude are null, don't add them to buffer + if (longitude === null || latitude === null) { + continue; + } + + buffer[i] = new Point(fromLonLat([longitude, latitude])); } return { From 60e9fb265ea31df8819d5dd1340951fc26117e0f Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 8 Aug 2022 09:34:12 +0100 Subject: [PATCH 17/30] Graphite: Use TimeRange with applied fiscalYearStartMonth (#51623) (#53370) * Parse date with fiscalYearStartMonth in graphite ds * Use precalculated timeranges * Always use precalculated values * Modify test (cherry picked from commit 5b058d617d2e74e390087866476f70d8332bed09) Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com> --- public/app/plugins/datasource/graphite/datasource.test.ts | 6 +++--- public/app/plugins/datasource/graphite/datasource.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/datasource/graphite/datasource.test.ts b/public/app/plugins/datasource/graphite/datasource.test.ts index 54ce71f387a..b0c271bbdeb 100644 --- a/public/app/plugins/datasource/graphite/datasource.test.ts +++ b/public/app/plugins/datasource/graphite/datasource.test.ts @@ -113,7 +113,7 @@ describe('graphiteDatasource', () => { const query = { panelId: 3, dashboardId: 5, - range: { raw: { from: 'now-1h', to: 'now' } }, + range: { from: dateTime('2022-04-01T00:00:00'), to: dateTime('2022-07-01T00:00:00') }, targets: [{ target: 'prod1.count' }, { target: 'prod2.count' }], maxDataPoints: 500, }; @@ -157,8 +157,8 @@ describe('graphiteDatasource', () => { const params = requestOptions.data.split('&'); expect(params).toContain('target=prod1.count'); expect(params).toContain('target=prod2.count'); - expect(params).toContain('from=-1h'); - expect(params).toContain('until=now'); + expect(params).toContain('from=1648789200'); + expect(params).toContain('until=1656655200'); }); it('should exclude undefined params', () => { diff --git a/public/app/plugins/datasource/graphite/datasource.ts b/public/app/plugins/datasource/graphite/datasource.ts index a83b90b2380..51d0a691a57 100644 --- a/public/app/plugins/datasource/graphite/datasource.ts +++ b/public/app/plugins/datasource/graphite/datasource.ts @@ -179,8 +179,8 @@ export class GraphiteDatasource query(options: DataQueryRequest): Observable { const graphOptions = { - from: this.translateTime(options.range.raw.from, false, options.timezone), - until: this.translateTime(options.range.raw.to, true, options.timezone), + from: this.translateTime(options.range.from, false, options.timezone), + until: this.translateTime(options.range.to, true, options.timezone), targets: options.targets, format: (options as any).format, cacheTimeout: options.cacheTimeout || this.cacheTimeout, From 95e3c91f637ff3357914adf5597c0f4069c081cd Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 8 Aug 2022 18:56:52 -0400 Subject: [PATCH 18/30] Prometheus: Remove metadata endpoint (#53428) (#53432) * remove prom metadata endpoint until we have a fix for detecting versions and implementations * fix linting issue (cherry picked from commit 7aeb8b4cdf0447d22f7936390f9946dadd4fb77d) Co-authored-by: Brendan O'Handley --- .../datasource/prometheus/language_provider.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/language_provider.ts b/public/app/plugins/datasource/prometheus/language_provider.ts index e88827e7cf7..fc8d14e0d10 100644 --- a/public/app/plugins/datasource/prometheus/language_provider.ts +++ b/public/app/plugins/datasource/prometheus/language_provider.ts @@ -18,7 +18,6 @@ import { PrometheusDatasource } from './datasource'; import { addLimitInfo, extractLabelMatchers, - fixSummariesMetadata, parseSelector, processHistogramMetrics, processLabels, @@ -146,9 +145,19 @@ export default class PromQlLanguageProvider extends LanguageProvider { }; async loadMetricsMetadata() { - this.metricsMetadata = fixSummariesMetadata( - await this.request('/api/v1/metadata', {}, {}, { showErrorAlert: false }) - ); + // The metadata endpoint is experimental and + // we have customers who are not implementing it. + // This is to be a temporary fix until the Observability Metrics Squad + // has time to implement the 2022Q3 plan + // to detect prometheus versions and implementations. + // This will allow us to see if endpoints such as api/v1/metadata + // are implemented or not and handle them as such + this.metricsMetadata = {}; + + // PREVIOUS IMPLEMENTATION FOR NOTES + // this.metricsMetadata = fixSummariesMetadata( + // await this.request('/api/v1/metadata', {}, {}, { showErrorAlert: false }) + // ); } getLabelKeys(): string[] { From fdfa380fa975bf844a6bdf766fa8f3f2021e74a8 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 9 Aug 2022 07:20:22 -0400 Subject: [PATCH 19/30] Dashboard Links: Fix styles for very long dashboard titles (#52443) (#52468) (cherry picked from commit 0142c8ccd1953126e178d981f6aa145da4891c06) Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> --- .betterer.results | 6 --- .../SubMenu/DashboardLinksDashboard.tsx | 49 +++++++++++++------ 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/.betterer.results b/.betterer.results index 21e4fe26dc3..747f18df0cc 100644 --- a/.betterer.results +++ b/.betterer.results @@ -4543,12 +4543,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], - "public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"] - ], "public/app/features/dashboard/components/SubMenu/SubMenu.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], diff --git a/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx b/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx index 53ccd630a0b..3b74510d7be 100644 --- a/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx +++ b/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx @@ -2,6 +2,7 @@ import { css, cx } from '@emotion/css'; import React, { useRef, useState, useLayoutEffect } from 'react'; import { useAsync } from 'react-use'; +import { GrafanaTheme2 } from '@grafana/data'; import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize'; import { selectors } from '@grafana/e2e-selectors'; import { Icon, ToolbarButton, Tooltip, useStyles2 } from '@grafana/ui'; @@ -14,7 +15,7 @@ import { DashboardLink } from '../../state/DashboardModel'; interface Props { link: DashboardLink; linkInfo: { title: string; href: string }; - dashboardId: any; + dashboardId: number; } export const DashboardLinksDashboard: React.FC = (props) => { @@ -23,13 +24,7 @@ export const DashboardLinksDashboard: React.FC = (props) => { const [dropdownCssClass, setDropdownCssClass] = useState('invisible'); const [opened, setOpened] = useState(0); const resolvedLinks = useResolvedLinks(props, opened); - - const buttonStyle = useStyles2( - (theme) => - css` - color: ${theme.colors.text.primary}; - ` - ); + const styles = useStyles2(getStyles); useLayoutEffect(() => { setDropdownCssClass(getDropdownLocationCssClass(listRef.current)); @@ -41,17 +36,22 @@ export const DashboardLinksDashboard: React.FC = (props) => { <> setOpened(Date.now())} - className={cx('gf-form-label gf-form-label--dashlink', buttonStyle)} + className={cx('gf-form-label gf-form-label--dashlink', styles.button)} data-placement="bottom" data-toggle="dropdown" aria-expanded={!!opened} aria-controls="dropdown-list" aria-haspopup="menu" > - + {linkInfo.title} -