From 1df622641c72135d55737574c331bc6393661690 Mon Sep 17 00:00:00 2001 From: Alexander Akhmetov Date: Tue, 3 Sep 2024 11:02:20 +0200 Subject: [PATCH 01/63] Alerting: Update documentation about alert instance limit (#92668) --- .../alerting/alerting-rules/create-grafana-managed-rule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md index 66d2e30c660..af1d74c7294 100644 --- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md +++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md @@ -83,7 +83,7 @@ Grafana-managed rules are the most flexible alert rule type. They allow you to c Multiple alert instances can be created as a result of one alert rule (also known as a multi-dimensional alerting). {{% admonition type="note" %}} -For Grafana Cloud, you can create 100 free Grafana-managed alert rules. +For Grafana Cloud Free Forever, you can create up to 100 free Grafana-managed alert rules with each alert rule having a maximum of 1000 alert instances. {{% /admonition %}} Grafana managed alert rules can only be edited or deleted by users with Edit permissions for the folder storing the rules. From d7d22bbbb8d1875d96a509e29d2b7bb8be681cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Jamr=C3=B3z?= Date: Tue, 3 Sep 2024 11:18:50 +0200 Subject: [PATCH 02/63] TraceView: Display event names of a span (#91382) * Display event name of a span * Clean up * Retrigger the build * Show colon only when there are fields to display * Rollback * Use event name when exporting to OTLP * Allow filtering spans by event name * Show duration as a key/value pair * Update betterer report (we do not translate panels that are planned to be externalized) * Fix tests after changing how duration is rendered * Handle long names * Test handling long names * Make parenthesis gray * Fix a test * Fix linting * Fix tests * Update label --- .betterer.results | 4 +- packages/grafana-data/src/types/trace.ts | 1 + pkg/tsdb/tempo/trace_transform.go | 8 +--- pkg/tsdb/tempo/trace_transform_test.go | 26 ++++++++++- .../SpanDetail/AccordianKeyValues.tsx | 20 +++++--- .../SpanDetail/AccordianLogs.test.tsx | 44 ++++++++++++++++++ .../SpanDetail/AccordianLogs.tsx | 46 +++++++++++++------ .../SpanDetail/KeyValuesTable.tsx | 3 +- .../TraceView/components/types/trace.ts | 1 + .../components/utils/filter-spans.test.ts | 5 ++ .../components/utils/filter-spans.tsx | 3 +- .../_importedDependencies/types/trace.ts | 1 + public/app/plugins/datasource/jaeger/types.ts | 1 + .../datasource/tempo/resultTransformer.ts | 4 +- .../datasource/tempo/test/testResponse.ts | 25 +++++++++- 15 files changed, 157 insertions(+), 35 deletions(-) diff --git a/.betterer.results b/.betterer.results index bafa487b8df..2f9307b0639 100644 --- a/.betterer.results +++ b/.betterer.results @@ -4096,7 +4096,9 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings. Wrap text with ", "4"], [0, 0, 0, "No untranslated strings. Wrap text with ", "5"], [0, 0, 0, "No untranslated strings. Wrap text with ", "6"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "7"] + [0, 0, 0, "No untranslated strings. Wrap text with ", "7"], + [0, 0, 0, "No untranslated strings. Wrap text with ", "8"], + [0, 0, 0, "No untranslated strings. Wrap text with ", "9"] ], "public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianReferences.tsx:5381": [ [0, 0, 0, "Styles should be written using objects.", "0"], diff --git a/packages/grafana-data/src/types/trace.ts b/packages/grafana-data/src/types/trace.ts index 27b16a9f73c..8346f07dfb9 100644 --- a/packages/grafana-data/src/types/trace.ts +++ b/packages/grafana-data/src/types/trace.ts @@ -13,6 +13,7 @@ export type TraceLog = { // Millisecond epoch time timestamp: number; fields: TraceKeyValuePair[]; + name?: string; }; export type TraceSpanReference = { diff --git a/pkg/tsdb/tempo/trace_transform.go b/pkg/tsdb/tempo/trace_transform.go index 0c3bf0321c2..a7d0f3c2dea 100644 --- a/pkg/tsdb/tempo/trace_transform.go +++ b/pkg/tsdb/tempo/trace_transform.go @@ -22,6 +22,7 @@ type TraceLog struct { // Millisecond epoch time Timestamp float64 `json:"timestamp"` Fields []*KeyValue `json:"fields"` + Name string `json:"name,omitempty"` } type TraceReference struct { @@ -260,12 +261,6 @@ func spanEventsToLogs(events ptrace.SpanEventSlice) []*TraceLog { for i := 0; i < events.Len(); i++ { event := events.At(i) fields := make([]*KeyValue, 0, event.Attributes().Len()+1) - if event.Name() != "" { - fields = append(fields, &KeyValue{ - Key: TagMessage, - Value: event.Name(), - }) - } event.Attributes().Range(func(key string, attr pcommon.Value) bool { fields = append(fields, &KeyValue{Key: key, Value: getAttributeVal(attr)}) return true @@ -273,6 +268,7 @@ func spanEventsToLogs(events ptrace.SpanEventSlice) []*TraceLog { logs = append(logs, &TraceLog{ Timestamp: float64(event.Timestamp()) / 1_000_000, Fields: fields, + Name: event.Name(), }) } diff --git a/pkg/tsdb/tempo/trace_transform_test.go b/pkg/tsdb/tempo/trace_transform_test.go index 8b901c6c41c..8253220655a 100644 --- a/pkg/tsdb/tempo/trace_transform_test.go +++ b/pkg/tsdb/tempo/trace_transform_test.go @@ -9,6 +9,7 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" "github.com/grafana/grafana-plugin-sdk-go/data" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -57,7 +58,30 @@ func TestTraceToFrame(t *testing.T) { require.Equal(t, json.RawMessage("[{\"value\":\"loki-all\",\"key\":\"service.name\"},{\"value\":\"Jaeger-Go-2.25.0\",\"key\":\"opencensus.exporterversion\"},{\"value\":\"4d019a031941\",\"key\":\"host.hostname\"},{\"value\":\"172.18.0.6\",\"key\":\"ip\"},{\"value\":\"4b19ace06df8e4de\",\"key\":\"client-uuid\"}]"), span["serviceTags"]) require.Equal(t, 1616072924072.852, span["startTime"]) require.Equal(t, 0.094, span["duration"]) - require.Equal(t, "[{\"timestamp\":1616072924072.856,\"fields\":[{\"value\":\"test event\",\"key\":\"message\"},{\"value\":1,\"key\":\"chunks requested\"}]},{\"timestamp\":1616072924072.9448,\"fields\":[{\"value\":1,\"key\":\"chunks fetched\"}]}]", string(span["logs"].(json.RawMessage))) + expectedLogs := ` + [ + { + "timestamp": 1616072924072.856, + "name": "test event", + "fields": [ + { + "value": 1, + "key": "chunks requested" + } + ] + }, + { + "timestamp": 1616072924072.9448, + "fields": [ + { + "value": 1, + "key": "chunks fetched" + } + ] + } + ] + ` + assert.JSONEq(t, expectedLogs, string(span["logs"].(json.RawMessage))) }) t.Run("should transform correct traceID", func(t *testing.T) { diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx index f2d0a4d9be2..29399e29552 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx @@ -67,7 +67,6 @@ export const getStyles = (theme: GrafanaTheme2) => { summaryItem: css` label: summaryItem; display: inline; - margin-left: 0.7em; padding-right: 0.5rem; border-right: 1px solid ${autoColor(theme, '#ddd')}; &:last-child { @@ -90,10 +89,11 @@ export const getStyles = (theme: GrafanaTheme2) => { export type AccordianKeyValuesProps = { className?: string | TNil; data: TraceKeyValuePair[]; + logName?: string; highContrast?: boolean; interactive?: boolean; isOpen: boolean; - label: string; + label: string | React.ReactNode; linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => TraceLink[]) | TNil; onToggle?: null | (() => void); }; @@ -127,6 +127,7 @@ export function KeyValuesSummary({ data = null }: KeyValuesSummaryProps) { export default function AccordianKeyValues({ className = null, data, + logName, highContrast = false, interactive = true, isOpen, @@ -134,11 +135,12 @@ export default function AccordianKeyValues({ linksGetter, onToggle = null, }: AccordianKeyValuesProps) { - const isEmpty = !Array.isArray(data) || !data.length; + const isEmpty = (!Array.isArray(data) || !data.length) && !logName; const styles = useStyles2(getStyles); const iconCls = cx(alignIcon, { [styles.emptyIcon]: isEmpty }); let arrow: React.ReactNode | null = null; let headerProps: {} | null = null; + const tableFields = logName ? [{ key: 'event name', value: logName }, ...data] : data; if (interactive) { arrow = isOpen ? ( @@ -152,6 +154,8 @@ export default function AccordianKeyValues({ }; } + const showDataSummaryFields = data.length > 0 && !isOpen; + return (
{label} - {isOpen || ':'} + {showDataSummaryFields && ':'} - {!isOpen && } + {showDataSummaryFields && ( + + + + )}
- {isOpen && } + {isOpen && }
); } diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.test.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.test.tsx index 8e5db8dcebd..f69f3c8808f 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.test.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.test.tsx @@ -30,6 +30,7 @@ const logs = [ { key: 'message', value: 'oh the next log message' }, { key: 'more', value: 'stuff' }, ], + name: 'foo event name', }, ]; @@ -72,4 +73,47 @@ describe('AccordianLogs tests', () => { expect(screen.getByText(/^something$/)).toBeInTheDocument(); expect(screen.getByText(/^else$/)).toBeInTheDocument(); }); + + it('shows log entries and long event name when expanded', () => { + const longNameLog = { + timestamp: 20, + name: 'This is a very very very very very very very long name', + fields: [{ key: 'foo', value: 'test' }], + }; + + setup({ + isOpen: true, + logs: [longNameLog], + openedItems: new Set([longNameLog]), + } as AccordianLogsProps); + + expect( + screen.getByRole('switch', { + name: '15μs (This is a very very ...)', + }) + ).toBeInTheDocument(); + + expect(screen.getByRole('table')).toBeInTheDocument(); + expect(screen.queryAllByRole('cell')).toHaveLength(6); + expect(screen.getByText(/^event name$/)).toBeInTheDocument(); + expect(screen.getByText(/This is a very very very very very very very long name/)).toBeInTheDocument(); + }); + + it('renders event name and duration when events list is closed', () => { + setup({ isOpen: true, openedItems: new Set() } as AccordianLogsProps); + expect( + screen.getByRole('switch', { + name: '15μs (foo event name) : message = oh the next log message more = stuff', + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('switch', { name: '5μs: message = oh the log message something = else' }) + ).toBeInTheDocument(); + }); + + it('renders event name and duration when events list is open', () => { + setup({ isOpen: true, openedItems: new Set(logs) } as AccordianLogsProps); + expect(screen.getByRole('switch', { name: '15μs (foo event name)' })).toBeInTheDocument(); + expect(screen.getByRole('switch', { name: '5μs' })).toBeInTheDocument(); + }); }); diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx index 9e8cefccd8c..6ecfec0f80d 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx @@ -59,6 +59,9 @@ const getStyles = (theme: GrafanaTheme2) => { AccordianKeyValuesItem: css({ marginBottom: theme.spacing(0.5), }), + parenthesis: css({ + color: `${autoColor(theme, '#777')}`, + }), }; }; @@ -108,22 +111,35 @@ export default function AccordianLogs({ {isOpen && (
- {_sortBy(logs, 'timestamp').map((log, i) => ( - onItemToggle(log) : null} - /> - ))} + {_sortBy(logs, 'timestamp').map((log, i) => { + const formattedDuration = formatDuration(log.timestamp - timestamp); + const truncateLogNameInSummary = log.name && log.name.length > 20; + const formattedLogName = log.name && truncateLogNameInSummary ? log.name.slice(0, 20) + '...' : log.name; + const label = formattedLogName ? ( + + {formattedDuration} ({formattedLogName}) + + ) : ( + formattedDuration + ); + return ( + onItemToggle(log) : null} + /> + ); + })} - Log timestamps are relative to the start time of the full trace. + Event timestamps are relative to the start time of the full trace.
)} diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx index 005d3af52ea..92b0731d467 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx @@ -48,7 +48,7 @@ export const getStyles = (theme: GrafanaTheme2) => { row: css` label: row; & > td { - padding: 0rem 0.5rem; + padding: 0.5rem 0.5rem; height: 30px; } &:nth-child(2n) > td { @@ -63,6 +63,7 @@ export const getStyles = (theme: GrafanaTheme2) => { color: ${autoColor(theme, '#888')}; white-space: pre; width: 125px; + vertical-align: top; `, copyColumn: css` label: copyColumn; diff --git a/public/app/features/explore/TraceView/components/types/trace.ts b/public/app/features/explore/TraceView/components/types/trace.ts index 0507287b987..bee45e059b4 100644 --- a/public/app/features/explore/TraceView/components/types/trace.ts +++ b/public/app/features/explore/TraceView/components/types/trace.ts @@ -31,6 +31,7 @@ export type TraceLink = { export type TraceLog = { timestamp: number; fields: TraceKeyValuePair[]; + name?: string; }; export type TraceProcess = { diff --git a/public/app/features/explore/TraceView/components/utils/filter-spans.test.ts b/public/app/features/explore/TraceView/components/utils/filter-spans.test.ts index 1cf04d8424a..4bae04a74a2 100644 --- a/public/app/features/explore/TraceView/components/utils/filter-spans.test.ts +++ b/public/app/features/explore/TraceView/components/utils/filter-spans.test.ts @@ -55,6 +55,7 @@ describe('filterSpans', () => { ], logs: [ { + name: 'logName0', fields: [ { key: 'logFieldKey0', @@ -316,6 +317,10 @@ describe('filterSpans', () => { ).toEqual(new Set([spanID0])); }); + it('it should return logs have a name which matches the filter', () => { + expect(filterSpans({ ...defaultFilters, query: 'logName0' }, spans)).toEqual(new Set([spanID0])); + }); + it('should return no spans when logs is null', () => { const nullSpan = { ...span0, logs: null }; expect( diff --git a/public/app/features/explore/TraceView/components/utils/filter-spans.tsx b/public/app/features/explore/TraceView/components/utils/filter-spans.tsx index 942a13a476b..9f6d908d52e 100644 --- a/public/app/features/explore/TraceView/components/utils/filter-spans.tsx +++ b/public/app/features/explore/TraceView/components/utils/filter-spans.tsx @@ -90,7 +90,8 @@ export function getQueryMatches(query: string, spans: TraceSpan[] | TNil) { (span.instrumentationLibraryName && isTextInQuery(queryParts, span.instrumentationLibraryName)) || (span.instrumentationLibraryVersion && isTextInQuery(queryParts, span.instrumentationLibraryVersion)) || (span.traceState && isTextInQuery(queryParts, span.traceState)) || - (span.logs !== null && span.logs.some((log) => isTextInKeyValues(log.fields))) || + (span.logs !== null && + span.logs.some((log) => (log.name && isTextInQuery(queryParts, log.name)) || isTextInKeyValues(log.fields))) || isTextInKeyValues(span.process.tags) || queryParts.some((queryPart) => queryPart === span.spanID); diff --git a/public/app/plugins/datasource/jaeger/_importedDependencies/types/trace.ts b/public/app/plugins/datasource/jaeger/_importedDependencies/types/trace.ts index 0507287b987..bee45e059b4 100644 --- a/public/app/plugins/datasource/jaeger/_importedDependencies/types/trace.ts +++ b/public/app/plugins/datasource/jaeger/_importedDependencies/types/trace.ts @@ -31,6 +31,7 @@ export type TraceLink = { export type TraceLog = { timestamp: number; fields: TraceKeyValuePair[]; + name?: string; }; export type TraceProcess = { diff --git a/public/app/plugins/datasource/jaeger/types.ts b/public/app/plugins/datasource/jaeger/types.ts index fe6778957f6..3fc5f8de320 100644 --- a/public/app/plugins/datasource/jaeger/types.ts +++ b/public/app/plugins/datasource/jaeger/types.ts @@ -14,6 +14,7 @@ export type TraceLink = { export type TraceLog = { timestamp: number; fields: TraceKeyValuePair[]; + name?: string; }; export type TraceProcess = { diff --git a/public/app/plugins/datasource/tempo/resultTransformer.ts b/public/app/plugins/datasource/tempo/resultTransformer.ts index 592b043307b..b41458590d1 100644 --- a/public/app/plugins/datasource/tempo/resultTransformer.ts +++ b/public/app/plugins/datasource/tempo/resultTransformer.ts @@ -132,7 +132,7 @@ function getLogs(span: collectorTypes.opentelemetryProto.trace.v1.Span) { fields.push({ key: attribute.key, value: getAttributeValue(attribute.value) }); } } - logs.push({ fields, timestamp: event.timeUnixNano / 1000000 }); + logs.push({ fields, timestamp: event.timeUnixNano / 1000000, name: event.name }); } } @@ -364,7 +364,7 @@ function getOTLPEvents(logs: TraceLog[]): collectorTypes.opentelemetryProto.trac timeUnixNano: log.timestamp * 1000000, attributes: [], droppedAttributesCount: 0, - name: '', + name: log.name || '', }; for (const field of log.fields) { event.attributes!.push({ diff --git a/public/app/plugins/datasource/tempo/test/testResponse.ts b/public/app/plugins/datasource/tempo/test/testResponse.ts index 493cb97501a..765e55cf08c 100644 --- a/public/app/plugins/datasource/tempo/test/testResponse.ts +++ b/public/app/plugins/datasource/tempo/test/testResponse.ts @@ -1920,7 +1920,7 @@ export const otlpDataFrameFromResponse = new MutableDataFrame({ name: 'logs', type: FieldType.other, config: {}, - values: [[]], + values: [[{ name: 'DNSDone', fields: [{ key: 'addr', value: '172.18.0.6' }] }]], }, { name: 'references', @@ -2138,7 +2138,20 @@ export const otlpDataFrameToResponse = new MutableDataFrame({ name: 'logs', type: FieldType.other, config: {}, - values: [[]], + values: [ + [ + { + fields: [ + { + key: 'addr', + value: '172.18.0.6', + }, + ], + timestamp: 1627471657255.809, + name: 'DNSDone', + }, + ], + ], state: { displayName: 'logs', }, @@ -2240,6 +2253,14 @@ export const otlpResponse = { { key: 'http.url', value: { stringValue: '/' } }, { key: 'component', value: { stringValue: 'net/http' } }, ], + events: [ + { + name: 'DNSDone', + attributes: [{ key: 'addr', value: { stringValue: '172.18.0.6' } }], + droppedAttributesCount: 0, + timeUnixNano: 1627471657255809000, + }, + ], links: [ { spanId: 'spanId', From 9dc333dfa75bb6721f492942474f2d4dd888173d Mon Sep 17 00:00:00 2001 From: Alexa V <239999+axelavargas@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:11:09 +0200 Subject: [PATCH 03/63] Dashboard Scene: Add close visualization button in panel edit (#92848) --- .../panel-edit/PanelVizTypePicker.tsx | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx b/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx index e4a8482622c..0da983abab6 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx @@ -3,7 +3,8 @@ import { useEffect, useMemo, useState } from 'react'; import { useLocalStorage } from 'react-use'; import { GrafanaTheme2, PanelData, SelectableValue } from '@grafana/data'; -import { CustomScrollbar, Field, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui'; +import { selectors } from '@grafana/e2e-selectors'; +import { Button, CustomScrollbar, Field, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui'; import { LS_VISUALIZATION_SELECT_TAB_KEY, LS_WIDGET_SELECT_TAB_KEY } from 'app/core/constants'; import { VisualizationSelectPaneTab } from 'app/features/dashboard/components/PanelEditor/types'; import { VisualizationSuggestions } from 'app/features/panel/components/VizTypePicker/VisualizationSuggestions'; @@ -61,15 +62,29 @@ export function PanelVizTypePicker({ vizManager, data, onChange }: Props) { onChange(); }; + const onCloseVizPicker = () => { + onChange(); + }; + return (
- +
+ +
@@ -106,6 +121,13 @@ const getStyles = (theme: GrafanaTheme2) => ({ borderBottom: 'none', borderTopLeftRadius: theme.shape.radius.default, }), + searchRow: css({ + display: 'flex', + marginBottom: theme.spacing(1), + }), + closeButton: css({ + marginLeft: theme.spacing(1), + }), customFieldMargin: css({ marginBottom: theme.spacing(1), }), From 46e81e98cfd2cda4fc9f8d361bfe612a7d569428 Mon Sep 17 00:00:00 2001 From: Ieva Date: Tue, 3 Sep 2024 11:30:47 +0100 Subject: [PATCH 04/63] RBAC: Always store action sets (#92833) always store action sets, even if FT is disabled --- pkg/services/accesscontrol/resourcepermissions/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/accesscontrol/resourcepermissions/store.go b/pkg/services/accesscontrol/resourcepermissions/store.go index 9ded47f4ab0..5e42f7b2784 100644 --- a/pkg/services/accesscontrol/resourcepermissions/store.go +++ b/pkg/services/accesscontrol/resourcepermissions/store.go @@ -725,7 +725,7 @@ func (s *store) createPermissions(sess *db.Session, roleID int64, cmd SetResourc } func (s *store) shouldStoreActionSet(resource, permission string) bool { - if !(s.features.IsEnabled(context.TODO(), featuremgmt.FlagAccessActionSets) && permission != "") { + if permission == "" { return false } actionSetName := GetActionSetName(resource, permission) From e7d7ed5406d7eecb9fe8ddfe5a30149526b55ff4 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 3 Sep 2024 12:43:13 +0200 Subject: [PATCH 05/63] Chore: Remove side-effect import from app (#92650) * chore(frontend): remove stray side-effect features import that brings the whole jungle * chore(app): delete features/all.ts and its friends * chore(codeowners): remove public/app/features/all.ts from file --- .github/CODEOWNERS | 1 - public/app/app.ts | 2 -- public/app/features/all.ts | 2 -- public/app/features/dashboard/index.ts | 7 ------- public/app/features/plugins/all.ts | 1 - 5 files changed, 13 deletions(-) delete mode 100644 public/app/features/all.ts delete mode 100644 public/app/features/dashboard/index.ts delete mode 100644 public/app/features/plugins/all.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5bc3cab07ce..eeb90d4556a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -403,7 +403,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/app/core/components/TimelineChart/ @grafana/dataviz-squad /public/app/core/components/Form/ @grafana/grafana-frontend-platform /public/app/core/history/ @grafana/explore-squad -/public/app/features/all.ts @grafana/grafana-frontend-platform /public/app/features/admin/ @grafana/identity-access-team # Temp owners until Enterprise team takes over diff --git a/public/app/app.ts b/public/app/app.ts index 6e6141e0d86..bc5dd608787 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -6,8 +6,6 @@ import 'file-saver'; import 'jquery'; import 'vendor/bootstrap/bootstrap'; -import 'app/features/all'; - import _ from 'lodash'; // eslint-disable-line lodash/import-scope import { createElement } from 'react'; import { createRoot } from 'react-dom/client'; diff --git a/public/app/features/all.ts b/public/app/features/all.ts deleted file mode 100644 index b25b7b50951..00000000000 --- a/public/app/features/all.ts +++ /dev/null @@ -1,2 +0,0 @@ -import './plugins/all'; -import './dashboard'; diff --git a/public/app/features/dashboard/index.ts b/public/app/features/dashboard/index.ts deleted file mode 100644 index 12c86883b58..00000000000 --- a/public/app/features/dashboard/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Services -import './services/DashboardLoaderSrv'; -import './services/DashboardSrv'; -// Components -import './components/DashExportModal'; -import './components/DashNav'; -import './components/DashboardSettings'; diff --git a/public/app/features/plugins/all.ts b/public/app/features/plugins/all.ts deleted file mode 100644 index fe460be0708..00000000000 --- a/public/app/features/plugins/all.ts +++ /dev/null @@ -1 +0,0 @@ -import './datasource_srv'; From 6c968f90aece6911d08f84d7a2f5a0387088ff2a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:08:09 +0000 Subject: [PATCH 06/63] Update dependency @grafana/scenes to v5.11.2 --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 146a96ce487..a6743b4c8f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3933,8 +3933,8 @@ __metadata: linkType: soft "@grafana/scenes@npm:^5.11.1": - version: 5.11.1 - resolution: "@grafana/scenes@npm:5.11.1" + version: 5.11.2 + resolution: "@grafana/scenes@npm:5.11.2" dependencies: "@floating-ui/react": "npm:0.26.16" "@grafana/e2e-selectors": "npm:^11.0.0" @@ -3951,7 +3951,7 @@ __metadata: "@grafana/ui": ">=10.4" react: ^18.0.0 react-dom: ^18.0.0 - checksum: 10/15ec8bee9aa2aa8f5c64ed9fcaf4bd7c835162e0e63814556e7561e62462d5485f098131e411893e54ae3247692b348c8773a9459c30e45e936c5b0ef1a9d789 + checksum: 10/1f6cded27acac813b1f039fa656efa476bcb2a444217c78c707441698d8d2dc053745fadcbad2dbe94a252d2613f1b32ac120fb11d887bb14f08a0bbea4c423b languageName: node linkType: hard From aa2175822e2e8dcbfc536cab55f3a161cb1e5a99 Mon Sep 17 00:00:00 2001 From: oscarkilhed Date: Tue, 3 Sep 2024 12:18:19 +0200 Subject: [PATCH 07/63] Fix bad mock in unittest --- .../panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx index 1726c669031..bfc51341d6c 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.test.tsx @@ -143,7 +143,7 @@ const dashboard = { from: 'now-6h', to: 'now', }, - timepicker: { refresh_intervals: 5 }, + timepicker: { refresh_intervals: ['5s', '30s', '1m'] }, meta: { canSave: true, folderId: 1, From d9385d8a76a915babde3aec9d9adbdf5f691d94a Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Tue, 3 Sep 2024 11:44:30 +0100 Subject: [PATCH 08/63] add missing await --- packages/grafana-ui/src/components/Combobox/Combobox.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx index b91cde4a618..2263618d601 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.test.tsx @@ -37,7 +37,7 @@ describe('Combobox', () => { render(); const input = screen.getByRole('combobox'); - userEvent.click(input); + await userEvent.click(input); const item = await screen.findByRole('option', { name: 'Option 1' }); await userEvent.click(item); From 1128c417d824e19e25224a0b0dcebbc28845f2cd Mon Sep 17 00:00:00 2001 From: Konrad Lalik Date: Tue, 3 Sep 2024 14:18:02 +0200 Subject: [PATCH 09/63] Alerting: Fix cloud rules edit url (#92853) Update cloud rule edit page url after successful update --- .../rule-editor/alert-rule-form/AlertRuleForm.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx index 39ac757ad67..22eda969175 100644 --- a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/AlertRuleForm.tsx @@ -14,6 +14,7 @@ import InfoPausedRule from 'app/features/alerting/unified/components/InfoPausedR import { getRuleGroupLocationFromFormValues, getRuleGroupLocationFromRuleWithLocation, + isCloudRulerRule, isGrafanaManagedRuleByType, isGrafanaRulerRule, isGrafanaRulerRulePaused, @@ -42,7 +43,7 @@ import { formValuesToRulerGrafanaRuleDTO, formValuesToRulerRuleDTO, } from '../../../utils/rule-form'; -import { fromRulerRuleAndRuleGroupIdentifier } from '../../../utils/rule-id'; +import { fromRulerRule, fromRulerRuleAndRuleGroupIdentifier, stringifyIdentifier } from '../../../utils/rule-id'; import { GrafanaRuleExporter } from '../../export/GrafanaRuleExporter'; import { AlertRuleNameAndMetric } from '../AlertRuleNameInput'; import AnnotationsStep from '../AnnotationsStep'; @@ -167,6 +168,10 @@ export const AlertRuleForm = ({ existing, prefill }: Props) => { if (exitOnSave && returnTo) { locationService.push(returnTo); + } else if (isCloudRulerRule(ruleDefinition)) { + const { dataSourceName, namespaceName, groupName } = getRuleGroupLocationFromFormValues(values); + const updatedRuleIdentifier = fromRulerRule(dataSourceName, namespaceName, groupName, ruleDefinition); + locationService.replace(`/alerting/${encodeURIComponent(stringifyIdentifier(updatedRuleIdentifier))}/edit`); } }; From e699a71340b87715e646c0df355775298b75ec02 Mon Sep 17 00:00:00 2001 From: Serge Zaitsev Date: Tue, 3 Sep 2024 14:43:36 +0200 Subject: [PATCH 10/63] Chore: Bump moby version (#92857) * bump moby version * update workspace --- go.work.sum | 2 ++ pkg/build/cmd/publishaws.go | 3 ++- pkg/build/go.mod | 5 +++-- pkg/build/go.sum | 12 ++++++++---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/go.work.sum b/go.work.sum index e1e7999bf90..83c7b457700 100644 --- a/go.work.sum +++ b/go.work.sum @@ -604,6 +604,8 @@ github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/drone/drone-runtime v1.1.0 h1:IsKbwiLY6+ViNBzX0F8PERJVZZcEJm9rgxEh3uZP5IE= github.com/drone/drone-runtime v1.1.0/go.mod h1:+osgwGADc/nyl40J0fdsf8Z09bgcBZXvXXnLOY48zYs= diff --git a/pkg/build/cmd/publishaws.go b/pkg/build/cmd/publishaws.go index 5fc98fbbc27..aa52ef6debc 100644 --- a/pkg/build/cmd/publishaws.go +++ b/pkg/build/cmd/publishaws.go @@ -16,6 +16,7 @@ import ( "github.com/aws/aws-sdk-go/service/ecr" "github.com/aws/aws-sdk-go/service/marketplacecatalog" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/registry" "github.com/docker/docker/client" "github.com/urfave/cli/v2" @@ -163,7 +164,7 @@ func (s *AwsMarketplacePublishingService) Login(ctx context.Context) error { return err } authString := strings.Split(string(authData), ":") - authData, err = json.Marshal(types.AuthConfig{ + authData, err = json.Marshal(registry.AuthConfig{ Username: authString[0], Password: authString[1], }) diff --git a/pkg/build/go.mod b/pkg/build/go.mod index c547676f24c..c5a7d9d3a56 100644 --- a/pkg/build/go.mod +++ b/pkg/build/go.mod @@ -5,7 +5,7 @@ go 1.23.0 // Override docker/docker to avoid: // go: github.com/drone-runners/drone-runner-docker@v1.8.2 requires // github.com/docker/docker@v0.0.0-00010101000000-000000000000: invalid version: unknown revision 000000000000 -replace github.com/docker/docker => github.com/moby/moby v23.0.4+incompatible +replace github.com/docker/docker => github.com/moby/moby v25.0.2+incompatible // contains openapi encoder fixes. remove ASAP replace cuelang.org/go => github.com/grafana/cue v0.0.0-20230926092038-971951014e3f // @grafana/grafana-as-code @@ -61,7 +61,6 @@ require ( github.com/buildkite/yaml v2.1.0+incompatible // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/drone-runners/drone-runner-docker v1.8.2 // indirect @@ -102,6 +101,8 @@ require ( github.com/Khan/genqlient v0.7.0 // indirect github.com/adrg/xdg v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/term v0.5.0 // indirect diff --git a/pkg/build/go.sum b/pkg/build/go.sum index 5eef149b39b..6ba9b002e92 100644 --- a/pkg/build/go.sum +++ b/pkg/build/go.sum @@ -54,6 +54,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -62,9 +64,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= @@ -168,8 +170,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/moby v23.0.4+incompatible h1:A/pe8vi9KIKhNbzR0G3wW4ACKDsMgXILBveMqiJNa8M= -github.com/moby/moby v23.0.4+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= +github.com/moby/moby v25.0.2+incompatible h1:g2oKRI7vgWkiPHZbBghaPbcV/SuKP1g/YLx0I2nxFT4= +github.com/moby/moby v25.0.2+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -195,6 +197,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 9d974f75602335ba8fdca391e5398f19f5b70b1f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:44:51 +0100 Subject: [PATCH 11/63] Update dependency @swc/helpers to v0.5.13 (#92858) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- yarn.lock | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index a6d5207cf8b..fd4d1e6b245 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "@rtk-query/codegen-openapi": "^1.2.0", "@rtsao/plugin-proposal-class-properties": "7.0.1-patch.1", "@swc/core": "1.4.2", - "@swc/helpers": "0.5.12", + "@swc/helpers": "0.5.13", "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "15.0.2", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 87ca2c1148a..9c5603f8682 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -81,7 +81,7 @@ "@rollup/plugin-image": "3.0.3", "@rollup/plugin-node-resolve": "15.2.3", "@swc/core": "1.4.2", - "@swc/helpers": "0.5.12", + "@swc/helpers": "0.5.13", "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "15.0.2", diff --git a/yarn.lock b/yarn.lock index a6743b4c8f6..ce58da223e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3769,7 +3769,7 @@ __metadata: "@rollup/plugin-image": "npm:3.0.3" "@rollup/plugin-node-resolve": "npm:15.2.3" "@swc/core": "npm:1.4.2" - "@swc/helpers": "npm:0.5.12" + "@swc/helpers": "npm:0.5.13" "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:6.4.2" "@testing-library/react": "npm:15.0.2" @@ -8822,12 +8822,12 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.12, @swc/helpers@npm:^0.5.0": - version: 0.5.12 - resolution: "@swc/helpers@npm:0.5.12" +"@swc/helpers@npm:0.5.13, @swc/helpers@npm:^0.5.0": + version: 0.5.13 + resolution: "@swc/helpers@npm:0.5.13" dependencies: tslib: "npm:^2.4.0" - checksum: 10/f04a4728c38a6e75a85b077408e175e1abbc1650a76e4b78008d6380ca1422d9f7f4f9fe61b42f8fb889140f05ced6a5a9983037a8d5d8086bf6bc80a0b2118b + checksum: 10/6ba2f7e215d32d71fce139e2cfc426b3ed7eaa709febdeb07b97260a4c9eea4784cf047cc1271be273990b08220b576b94a42b5780947c0b3be84973a847a24d languageName: node linkType: hard @@ -18547,7 +18547,7 @@ __metadata: "@rtk-query/codegen-openapi": "npm:^1.2.0" "@rtsao/plugin-proposal-class-properties": "npm:7.0.1-patch.1" "@swc/core": "npm:1.4.2" - "@swc/helpers": "npm:0.5.12" + "@swc/helpers": "npm:0.5.13" "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:6.4.2" "@testing-library/react": "npm:15.0.2" From f34f5b80b4868d7210cd4efd41f040731d8997da Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Tue, 3 Sep 2024 14:04:21 +0100 Subject: [PATCH 12/63] Chore: Migrate `_widths` SCSS to global emotion styles (#92863) * migrate widths to global styles * only calculate width once per loop --- .../src/themes/GlobalStyles/utilityClasses.ts | 23 +++++++++++++ public/sass/_angular.scss | 4 +++ public/sass/_grafana.scss | 3 -- public/sass/utils/_widths.scss | 32 ------------------- 4 files changed, 27 insertions(+), 35 deletions(-) delete mode 100644 public/sass/utils/_widths.scss diff --git a/packages/grafana-ui/src/themes/GlobalStyles/utilityClasses.ts b/packages/grafana-ui/src/themes/GlobalStyles/utilityClasses.ts index 9a2fea24cf5..ef3a927c31b 100644 --- a/packages/grafana-ui/src/themes/GlobalStyles/utilityClasses.ts +++ b/packages/grafana-ui/src/themes/GlobalStyles/utilityClasses.ts @@ -1,3 +1,4 @@ +import { CSSInterpolation } from '@emotion/css'; import { css } from '@emotion/react'; import { GrafanaTheme2 } from '@grafana/data'; @@ -33,6 +34,27 @@ function buttonSizeMixin(paddingY: string, paddingX: string, fontSize: string, b }; } +function widthMixin(theme: GrafanaTheme2, max: number) { + let result: CSSInterpolation = {}; + for (let i = 1; i <= max; i++) { + const width = `${theme.spacing(2 * i)} !important`; + result[`.width-${i}`] = { + width, + }; + result[`.max-width-${i}`] = { + maxWidth: width, + flexGrow: 1, + }; + result[`.min-width-${i}`] = { + minWidth: width, + }; + result[`.offset-width-${i}`] = { + marginLeft: width, + }; + } + return result; +} + export function getUtilityClassStyles(theme: GrafanaTheme2) { return css({ '.highlight-word': { @@ -140,5 +162,6 @@ export function getUtilityClassStyles(theme: GrafanaTheme2) { '.typeahead': { zIndex: theme.zIndex.typeahead, }, + ...widthMixin(theme, 30), }); } diff --git a/public/sass/_angular.scss b/public/sass/_angular.scss index fce198b2516..33e6364f4c9 100644 --- a/public/sass/_angular.scss +++ b/public/sass/_angular.scss @@ -2602,3 +2602,7 @@ label.cr1 { input[type='checkbox'].cr1:checked + label { background: url($checkboxImageUrl) 0px -18px no-repeat; } + +.max-width { + width: 100%; +} diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index e54884826f3..d0f36791e03 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -3,8 +3,5 @@ @import 'base/grid'; @import 'base/font_awesome'; -// UTILS -@import 'utils/widths'; - // ANGULAR @import 'angular'; diff --git a/public/sass/utils/_widths.scss b/public/sass/utils/_widths.scss deleted file mode 100644 index e996ae564f0..00000000000 --- a/public/sass/utils/_widths.scss +++ /dev/null @@ -1,32 +0,0 @@ -.max-width { - width: 100%; -} -.width-auto { - width: auto; -} - -// widths -@for $i from 1 through 30 { - .width-#{$i} { - width: ($spacer * $i) !important; - } -} - -@for $i from 1 through 30 { - .max-width-#{$i} { - max-width: ($spacer * $i) !important; - flex-grow: 1; - } -} - -@for $i from 1 through 30 { - .min-width-#{$i} { - min-width: ($spacer * $i) !important; - } -} - -@for $i from 1 through 30 { - .offset-width-#{$i} { - margin-left: ($spacer * $i) !important; - } -} From 351864653b9990adf609a8c08fc9a1d945981f7b Mon Sep 17 00:00:00 2001 From: Ivan Ortega Alba Date: Tue, 3 Sep 2024 15:05:21 +0200 Subject: [PATCH 13/63] Scenes: Upgrade to v5.12.0 (#92862) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index fd4d1e6b245..5a0ae41e464 100644 --- a/package.json +++ b/package.json @@ -268,7 +268,7 @@ "@grafana/prometheus": "workspace:*", "@grafana/runtime": "workspace:*", "@grafana/saga-icons": "workspace:*", - "@grafana/scenes": "^5.11.1", + "@grafana/scenes": "5.12.0", "@grafana/schema": "workspace:*", "@grafana/sql": "workspace:*", "@grafana/ui": "workspace:*", diff --git a/yarn.lock b/yarn.lock index ce58da223e2..c72cd11c338 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3932,9 +3932,9 @@ __metadata: languageName: unknown linkType: soft -"@grafana/scenes@npm:^5.11.1": - version: 5.11.2 - resolution: "@grafana/scenes@npm:5.11.2" +"@grafana/scenes@npm:5.12.0": + version: 5.12.0 + resolution: "@grafana/scenes@npm:5.12.0" dependencies: "@floating-ui/react": "npm:0.26.16" "@grafana/e2e-selectors": "npm:^11.0.0" @@ -3951,7 +3951,7 @@ __metadata: "@grafana/ui": ">=10.4" react: ^18.0.0 react-dom: ^18.0.0 - checksum: 10/1f6cded27acac813b1f039fa656efa476bcb2a444217c78c707441698d8d2dc053745fadcbad2dbe94a252d2613f1b32ac120fb11d887bb14f08a0bbea4c423b + checksum: 10/17e1e1b2928c06ad9c898e1988ece2a2113ca3177f510036b42eb4032d6582e783ec28f1f3110dc67acda4ec56d2747ae23c2d57593bc2dac0ff60b2fffeda61 languageName: node linkType: hard @@ -18511,7 +18511,7 @@ __metadata: "@grafana/prometheus": "workspace:*" "@grafana/runtime": "workspace:*" "@grafana/saga-icons": "workspace:*" - "@grafana/scenes": "npm:^5.11.1" + "@grafana/scenes": "npm:5.12.0" "@grafana/schema": "workspace:*" "@grafana/sql": "workspace:*" "@grafana/tsconfig": "npm:^2.0.0" From 6244c2be2c56ae5370f3fc4032b027118baae30f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:48:06 +0000 Subject: [PATCH 14/63] Update dependency eslint-plugin-jest to v28.8.2 --- package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- yarn.lock | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 5a0ae41e464..ff22c3643e6 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "28.8.1", + "eslint-plugin-jest": "28.8.2", "eslint-plugin-jest-dom": "^5.4.0", "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-jsx-a11y": "6.9.0", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 9c5603f8682..47d2b0f2912 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -110,7 +110,7 @@ "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "28.8.1", + "eslint-plugin-jest": "28.8.2", "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-jsx-a11y": "6.9.0", "eslint-plugin-lodash": "7.4.0", diff --git a/yarn.lock b/yarn.lock index c72cd11c338..52aa1cd733d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3801,7 +3801,7 @@ __metadata: eslint: "npm:8.57.0" eslint-config-prettier: "npm:9.1.0" eslint-plugin-import: "npm:^2.26.0" - eslint-plugin-jest: "npm:28.8.1" + eslint-plugin-jest: "npm:28.8.2" eslint-plugin-jsdoc: "npm:48.11.0" eslint-plugin-jsx-a11y: "npm:6.9.0" eslint-plugin-lodash: "npm:7.4.0" @@ -16588,9 +16588,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jest@npm:28.8.1": - version: 28.8.1 - resolution: "eslint-plugin-jest@npm:28.8.1" +"eslint-plugin-jest@npm:28.8.2": + version: 28.8.2 + resolution: "eslint-plugin-jest@npm:28.8.2" dependencies: "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: @@ -16602,7 +16602,7 @@ __metadata: optional: true jest: optional: true - checksum: 10/d148255d9e131103fc6be708874043f679c84137db140832523ab2481d17683d13ed41a15626f24b098ba5674520c1c316243a02d32d64f87cede57b0d84a46a + checksum: 10/5868bc0f825fdb5c26ff5939a55baa6e6b9bf9c7de5a45388babb876b17e0253a1e8c4d343b404fd5fcd2b7ab1808b47e20b06fb193a4e73f145fe25473eada4 languageName: node linkType: hard @@ -18657,7 +18657,7 @@ __metadata: eslint: "npm:8.57.0" eslint-config-prettier: "npm:9.1.0" eslint-plugin-import: "npm:^2.26.0" - eslint-plugin-jest: "npm:28.8.1" + eslint-plugin-jest: "npm:28.8.2" eslint-plugin-jest-dom: "npm:^5.4.0" eslint-plugin-jsdoc: "npm:48.11.0" eslint-plugin-jsx-a11y: "npm:6.9.0" From 88259da745a82adcc1776c29be810519b3abc0ec Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Tue, 3 Sep 2024 15:46:56 +0200 Subject: [PATCH 15/63] RBAC: Optimize permissions caching (#92673) * Access control: Use composite cache key for team permissions * use composite key for teams * use cache for hotpath (getCachedUserPermissions) * don't cache empty teams set * don't pass permissions as argument * early return if no teams found * reload cache correctly * optimize allocations * Clear user's teams cache * remove composite cache for teams * fix linter * don't clear teams permissions * pre-allocate memory for basic roles permissions --- pkg/services/accesscontrol/acimpl/service.go | 44 +++++++++++++------ pkg/services/accesscontrol/cacheutils.go | 2 +- pkg/services/accesscontrol/cacheutils_test.go | 3 +- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index 8d45bfb2677..3d5502afbf1 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/otel/attribute" "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/infra/db" @@ -241,32 +242,40 @@ func (s *Service) getCachedUserPermissions(ctx context.Context, user identity.Re ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedUserPermissions") defer span.End() - permissions := []accesscontrol.Permission{} - permissions, err := s.getCachedBasicRolesPermissions(ctx, user, options, permissions) + cacheKey := accesscontrol.GetUserPermissionCacheKey(user) + if cachedPermissions, ok := s.cache.Get(cacheKey); ok { + return cachedPermissions.([]accesscontrol.Permission), nil + } + + permissions, err := s.getCachedBasicRolesPermissions(ctx, user, options) if err != nil { return nil, err } - permissions, err = s.getCachedTeamsPermissions(ctx, user, options, permissions) + teamsPermissions, err := s.getCachedTeamsPermissions(ctx, user, options) + if err != nil { + return nil, err + } + permissions = append(permissions, teamsPermissions...) + + userManagedPermissions, err := s.getCachedUserDirectPermissions(ctx, user, options) if err != nil { return nil, err } - userPermissions, err := s.getCachedUserDirectPermissions(ctx, user, options) - if err != nil { - return nil, err - } - - permissions = append(permissions, userPermissions...) + permissions = append(permissions, userManagedPermissions...) + s.cache.Set(cacheKey, permissions, cacheTTL) span.SetAttributes(attribute.Int("num_permissions", len(permissions))) return permissions, nil } -func (s *Service) getCachedBasicRolesPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options, permissions []accesscontrol.Permission) ([]accesscontrol.Permission, error) { +func (s *Service) getCachedBasicRolesPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) { ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedBasicRolesPermissions") defer span.End() + // Viewer role has ~30 permissions, so we can pre-allocate memory + permissions := make([]accesscontrol.Permission, 0, 50) basicRoles := accesscontrol.GetOrgRoles(user) span.SetAttributes(attribute.Int("roles", len(basicRoles))) for _, role := range basicRoles { @@ -330,16 +339,20 @@ func (s *Service) getCachedPermissions(ctx context.Context, key string, getPermi return permissions, nil } -func (s *Service) getCachedTeamsPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options, permissions []accesscontrol.Permission) ([]accesscontrol.Permission, error) { +func (s *Service) getCachedTeamsPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) { ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedTeamsPermissions") defer span.End() teams := user.GetTeams() orgID := user.GetOrgID() - miss := teams + if len(teams) == 0 { + return []accesscontrol.Permission{}, nil + } + + miss := make([]int64, 0) + permissions := make([]accesscontrol.Permission, 0) if !options.ReloadCache { - miss = make([]int64, 0) for _, teamID := range teams { key := accesscontrol.GetTeamPermissionCacheKey(teamID, orgID) teamPermissions, ok := s.cache.Get(key) @@ -351,6 +364,9 @@ func (s *Service) getCachedTeamsPermissions(ctx context.Context, user identity.R miss = append(miss, teamID) } } + } else { + // reload cache and fetch all teams permissions + miss = teams } if len(miss) > 0 { @@ -373,7 +389,7 @@ func (s *Service) getCachedTeamsPermissions(ctx context.Context, user identity.R } func (s *Service) ClearUserPermissionCache(user identity.Requester) { - s.cache.Delete(accesscontrol.GetPermissionCacheKey(user)) + s.cache.Delete(accesscontrol.GetUserPermissionCacheKey(user)) s.cache.Delete(accesscontrol.GetUserDirectPermissionCacheKey(user)) } diff --git a/pkg/services/accesscontrol/cacheutils.go b/pkg/services/accesscontrol/cacheutils.go index 9326d9d88c8..39d1d1a45f8 100644 --- a/pkg/services/accesscontrol/cacheutils.go +++ b/pkg/services/accesscontrol/cacheutils.go @@ -7,7 +7,7 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/identity" ) -func GetPermissionCacheKey(user identity.Requester) string { +func GetUserPermissionCacheKey(user identity.Requester) string { return fmt.Sprintf("rbac-permissions-%s", user.GetCacheKey()) } diff --git a/pkg/services/accesscontrol/cacheutils_test.go b/pkg/services/accesscontrol/cacheutils_test.go index 7aff7941586..c5bf747b60b 100644 --- a/pkg/services/accesscontrol/cacheutils_test.go +++ b/pkg/services/accesscontrol/cacheutils_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/user" ) @@ -68,7 +69,7 @@ func TestPermissionCacheKey(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - assert.Equal(t, tc.expected, GetPermissionCacheKey(tc.signedInUser)) + assert.Equal(t, tc.expected, GetUserPermissionCacheKey(tc.signedInUser)) }) } } From d382ea773a3eeef18ac41650073ae083e7faa381 Mon Sep 17 00:00:00 2001 From: Kyle Brandt Date: Tue, 3 Sep 2024 09:56:25 -0400 Subject: [PATCH 16/63] Prometheus: Enable the promQLScope (Scopes, Adhoc filters and groupby) by default (#92080) --- .../configure-grafana/feature-toggles/index.md | 2 +- pkg/promlib/models/query.go | 8 +++++--- pkg/services/featuremgmt/registry.go | 3 ++- pkg/services/featuremgmt/toggles_gen.csv | 2 +- pkg/services/featuremgmt/toggles_gen.json | 12 ++++++++---- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index a0fae3e97e7..b3dda154598 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -62,6 +62,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general- | `logRowsPopoverMenu` | Enable filtering menu displayed when text of a log line is selected | Yes | | `lokiQueryHints` | Enables query hints for Loki | Yes | | `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | | +| `promQLScope` | In-development feature that will allow injection of labels into prometheus queries. | Yes | | `groupToNestedTableTransformation` | Enables the group to nested table transformation | Yes | | `tlsMemcached` | Use TLS-enabled memcached in the enterprise caching feature | Yes | | `cloudWatchNewLabelParsing` | Updates CloudWatch label parsing to be more accurate | Yes | @@ -172,7 +173,6 @@ Experimental features might be changed or removed without prior notice. | `tableSharedCrosshair` | Enables shared crosshair in table panel | | `kubernetesFeatureToggles` | Use the kubernetes API for feature toggle management in the frontend | | `newFolderPicker` | Enables the nested folder picker without having nested folders enabled | -| `promQLScope` | In-development feature that will allow injection of labels into prometheus queries. | | `sqlExpressions` | Enables using SQL and DuckDB functions as Expressions. | | `nodeGraphDotLayout` | Changed the layout algorithm for the node graph | | `kubernetesAggregator` | Enable grafana's embedded kube-aggregator | diff --git a/pkg/promlib/models/query.go b/pkg/promlib/models/query.go index 02031d4cb16..8acd496a264 100644 --- a/pkg/promlib/models/query.go +++ b/pkg/promlib/models/query.go @@ -238,9 +238,11 @@ func Parse(span trace.Span, query backend.DataQuery, dsScrapeInterval string, in }())) } - expr, err = ApplyFiltersAndGroupBy(expr, scopeFilters, model.AdhocFilters, model.GroupByKeys) - if err != nil { - return nil, err + if len(scopeFilters) > 0 || len(model.AdhocFilters) > 0 || len(model.GroupByKeys) > 0 { + expr, err = ApplyFiltersAndGroupBy(expr, scopeFilters, model.AdhocFilters, model.GroupByKeys) + if err != nil { + return nil, err + } } } diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index a0c513ccc49..dc6d06ee8bc 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1039,8 +1039,9 @@ var ( { Name: "promQLScope", Description: "In-development feature that will allow injection of labels into prometheus queries.", - Stage: FeatureStageExperimental, + Stage: FeatureStageGeneralAvailability, Owner: grafanaObservabilityMetricsSquad, + Expression: "true", }, { Name: "sqlExpressions", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index dab6db0193c..407c96eb20b 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -136,7 +136,7 @@ newFolderPicker,experimental,@grafana/grafana-frontend-platform,false,false,true jitterAlertRulesWithinGroups,preview,@grafana/alerting-squad,false,true,false onPremToCloudMigrations,preview,@grafana/grafana-operator-experience-squad,false,false,false alertingSaveStatePeriodic,privatePreview,@grafana/alerting-squad,false,false,false -promQLScope,experimental,@grafana/observability-metrics,false,false,false +promQLScope,GA,@grafana/observability-metrics,false,false,false sqlExpressions,experimental,@grafana/grafana-app-platform-squad,false,false,false nodeGraphDotLayout,experimental,@grafana/observability-traces-and-profiling,false,false,true groupToNestedTableTransformation,GA,@grafana/dataviz-squad,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 3a724d7c90b..43b2e7a8039 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2188,13 +2188,17 @@ { "metadata": { "name": "promQLScope", - "resourceVersion": "1718727528075", - "creationTimestamp": "2024-01-29T20:22:17Z" + "resourceVersion": "1724076197892", + "creationTimestamp": "2024-01-29T20:22:17Z", + "annotations": { + "grafana.app/updatedTimestamp": "2024-08-19 14:03:17.892558375 +0000 UTC" + } }, "spec": { "description": "In-development feature that will allow injection of labels into prometheus queries.", - "stage": "experimental", - "codeowner": "@grafana/observability-metrics" + "stage": "GA", + "codeowner": "@grafana/observability-metrics", + "expression": "true" } }, { From cb9c7de0ffff191eaeff0bc05db7185f7e990099 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:37:45 +0000 Subject: [PATCH 17/63] Update dependency eslint-plugin-react to v7.35.1 --- package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- yarn.lock | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index ff22c3643e6..7d4fda49a3b 100644 --- a/package.json +++ b/package.json @@ -181,7 +181,7 @@ "eslint-plugin-jsx-a11y": "6.9.0", "eslint-plugin-lodash": "7.4.0", "eslint-plugin-no-barrel-files": "^1.1.0", - "eslint-plugin-react": "7.35.0", + "eslint-plugin-react": "7.35.1", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-testing-library": "^6.2.2", "eslint-scope": "^8.0.0", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 47d2b0f2912..1982895a0c8 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -114,7 +114,7 @@ "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-jsx-a11y": "6.9.0", "eslint-plugin-lodash": "7.4.0", - "eslint-plugin-react": "7.35.0", + "eslint-plugin-react": "7.35.1", "eslint-plugin-react-hooks": "4.6.0", "eslint-webpack-plugin": "4.2.0", "fork-ts-checker-webpack-plugin": "9.0.2", diff --git a/yarn.lock b/yarn.lock index 52aa1cd733d..ccb4badd599 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3805,7 +3805,7 @@ __metadata: eslint-plugin-jsdoc: "npm:48.11.0" eslint-plugin-jsx-a11y: "npm:6.9.0" eslint-plugin-lodash: "npm:7.4.0" - eslint-plugin-react: "npm:7.35.0" + eslint-plugin-react: "npm:7.35.1" eslint-plugin-react-hooks: "npm:4.6.0" eslint-webpack-plugin: "npm:4.2.0" eventemitter3: "npm:5.0.1" @@ -16727,9 +16727,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react@npm:7.35.0": - version: 7.35.0 - resolution: "eslint-plugin-react@npm:7.35.0" +"eslint-plugin-react@npm:7.35.1": + version: 7.35.1 + resolution: "eslint-plugin-react@npm:7.35.1" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -16751,7 +16751,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10/fa0a54f9ea249cf89d92bb5983bf7df741da3709a0ebd6a885a67d05413ed302fd8b64c9dc819b33df8efa6d8b06f5e56b1f6965a9be7cc3e79054da4dbae5ed + checksum: 10/5bbae54dcef5a84bd71277315238d63caaa23effecd1a376b83ccf1cf033770ee44b763300f9fb55c569d7688ebc93d12728018dcfe240423c6059cc7284ba3f languageName: node linkType: hard @@ -18663,7 +18663,7 @@ __metadata: eslint-plugin-jsx-a11y: "npm:6.9.0" eslint-plugin-lodash: "npm:7.4.0" eslint-plugin-no-barrel-files: "npm:^1.1.0" - eslint-plugin-react: "npm:7.35.0" + eslint-plugin-react: "npm:7.35.1" eslint-plugin-react-hooks: "npm:4.6.0" eslint-plugin-testing-library: "npm:^6.2.2" eslint-scope: "npm:^8.0.0" From 2bbce8a7f79d6e79f86e336db9f5fc321e1d19b9 Mon Sep 17 00:00:00 2001 From: Victor Marin <36818606+mdvictor@users.noreply.github.com> Date: Tue, 3 Sep 2024 17:12:55 +0300 Subject: [PATCH 18/63] DashboardScene: Re-perform repeat when returning to dashboard from panel edit (#92754) * Reset prev values on panel deactivation/reactivation * add comments * fix * add test --- .../scene/DashboardGridItem.test.tsx | 145 +++++++++++++++++- .../scene/DashboardGridItem.tsx | 6 + 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard-scene/scene/DashboardGridItem.test.tsx b/public/app/features/dashboard-scene/scene/DashboardGridItem.test.tsx index b09427095b3..e6d202b0801 100644 --- a/public/app/features/dashboard-scene/scene/DashboardGridItem.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardGridItem.test.tsx @@ -1,11 +1,18 @@ import { VariableRefresh } from '@grafana/data'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { setPluginImportUtils } from '@grafana/runtime'; -import { SceneGridLayout, VizPanel } from '@grafana/scenes'; +import { SceneGridLayout, SceneVariableSet, TestVariable, VizPanel } from '@grafana/scenes'; +import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants'; import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils'; import { DashboardGridItem, DashboardGridItemState } from './DashboardGridItem'; +import { DashboardScene } from './DashboardScene'; + +jest.mock('@grafana/runtime', () => ({ + ...jest.requireActual('@grafana/runtime'), + getPluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }), +})); setPluginImportUtils({ importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})), @@ -85,6 +92,142 @@ describe('PanelRepeaterGridItem', () => { expect(repeater.state.repeatedPanels?.length).toBe(1); }); + it('Should redo the repeat when editing panel and then returning to dashboard', async () => { + const panel = new DashboardGridItem({ + variableName: 'server', + repeatedPanels: [], + body: new VizPanel({ + title: 'Panel $server', + }), + }); + + const variable = new TestVariable({ + name: 'server', + query: 'A.*', + value: ALL_VARIABLE_VALUE, + text: ALL_VARIABLE_TEXT, + isMulti: true, + includeAll: true, + delayMs: 0, + optionsToReturn: [ + { label: 'A', value: '1' }, + { label: 'B', value: '2' }, + { label: 'C', value: '3' }, + { label: 'D', value: '4' }, + { label: 'E', value: '5' }, + ], + }); + + const scene = new DashboardScene({ + $variables: new SceneVariableSet({ + variables: [variable], + }), + body: new SceneGridLayout({ + children: [panel], + }), + }); + + const deactivate = activateFullSceneTree(scene); + + await new Promise((r) => setTimeout(r, 10)); + + expect(panel.state.repeatedPanels?.length).toBe(5); + + const vizPanel = panel.state.body as VizPanel; + + expect(vizPanel.state.title).toBe('Panel $server'); + + // mimic going to panel edit + deactivate(); + + await new Promise((r) => setTimeout(r, 10)); + + vizPanel.setState({ title: 'Changed' }); + //mimic returning to dashboard from panel edit cloning panel + panel.setState({ body: vizPanel.clone() }); + + // mimic returning to dashboard + activateFullSceneTree(scene); + + await new Promise((r) => setTimeout(r, 10)); + + expect(panel.state.repeatedPanels?.length).toBe(5); + expect((panel.state.repeatedPanels![0] as VizPanel).state.title).toBe('Changed'); + }); + + it('Should only redo the repeat of an edited panel, not all panels in dashboard', async () => { + const panel = new DashboardGridItem({ + variableName: 'server', + repeatedPanels: [], + body: new VizPanel({ + title: 'Panel $server', + }), + }); + + const panel2 = new DashboardGridItem({ + variableName: 'server', + repeatedPanels: [], + body: new VizPanel({ + title: 'Panel $server 2', + }), + }); + + const variable = new TestVariable({ + name: 'server', + query: 'A.*', + value: ALL_VARIABLE_VALUE, + text: ALL_VARIABLE_TEXT, + isMulti: true, + includeAll: true, + delayMs: 0, + optionsToReturn: [ + { label: 'A', value: '1' }, + { label: 'B', value: '2' }, + { label: 'C', value: '3' }, + { label: 'D', value: '4' }, + { label: 'E', value: '5' }, + ], + }); + + const scene = new DashboardScene({ + $variables: new SceneVariableSet({ + variables: [variable], + }), + body: new SceneGridLayout({ + children: [panel, panel2], + }), + }); + + const deactivate = activateFullSceneTree(scene); + + await new Promise((r) => setTimeout(r, 10)); + + expect(panel.state.repeatedPanels?.length).toBe(5); + + const vizPanel = panel.state.body as VizPanel; + + expect(vizPanel.state.title).toBe('Panel $server'); + + // mimic going to panel edit + deactivate(); + + await new Promise((r) => setTimeout(r, 10)); + + vizPanel.setState({ title: 'Changed' }); + //mimic returning to dashboard from panel edit cloning panel + panel.setState({ body: vizPanel.clone() }); + + const performRepeatMock = jest.spyOn(panel, 'performRepeat'); + // mimic returning to dashboard + activateFullSceneTree(scene); + + await new Promise((r) => setTimeout(r, 10)); + + expect(performRepeatMock).toHaveBeenCalledTimes(1); // only for the edited panel + expect(panel.state.repeatedPanels?.length).toBe(5); + expect((panel.state.repeatedPanels![0] as VizPanel).state.title).toBe('Changed'); + }); + it('Should display a panel when there are variable errors', () => { const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, diff --git a/public/app/features/dashboard-scene/scene/DashboardGridItem.tsx b/public/app/features/dashboard-scene/scene/DashboardGridItem.tsx index 670a57b9f98..cfdbaea407c 100644 --- a/public/app/features/dashboard-scene/scene/DashboardGridItem.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardGridItem.tsx @@ -45,6 +45,7 @@ export type RepeatDirection = 'v' | 'h'; export class DashboardGridItem extends SceneObjectBase implements SceneGridItemLike { private _libPanelSubscription: Unsubscribable | undefined; private _prevRepeatValues?: VariableValueSingle[]; + private _oldBody?: VizPanel | LibraryVizPanel | AddLibraryPanelDrawer; protected _variableDependency = new DashboardGridItemVariableDependencyHandler(this); @@ -57,6 +58,11 @@ export class DashboardGridItem extends SceneObjectBase i private _activationHandler() { if (this.state.variableName) { this._subs.add(this.subscribeToState((newState, prevState) => this._handleGridResize(newState, prevState))); + if (this._oldBody !== this.state.body) { + this._prevRepeatValues = undefined; + } + + this._oldBody = this.state.body; this.performRepeat(); } From 5a3acbb15d81af3f3ce0ecce24ae7f7febc6e00e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:59:45 +0000 Subject: [PATCH 19/63] Update dependency postcss to v8.4.44 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7d4fda49a3b..b41c1e3f513 100644 --- a/package.json +++ b/package.json @@ -210,7 +210,7 @@ "ngtemplate-loader": "2.1.0", "node-notifier": "10.0.1", "nx": "19.2.0", - "postcss": "8.4.41", + "postcss": "8.4.44", "postcss-loader": "8.1.1", "postcss-reporter": "7.1.0", "postcss-scss": "4.0.9", diff --git a/yarn.lock b/yarn.lock index ccb4badd599..01b43249786 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18726,7 +18726,7 @@ __metadata: ol: "npm:7.4.0" ol-ext: "npm:4.0.23" pluralize: "npm:^8.0.0" - postcss: "npm:8.4.41" + postcss: "npm:8.4.44" postcss-loader: "npm:8.1.1" postcss-reporter: "npm:7.1.0" postcss-scss: "npm:4.0.9" @@ -25913,14 +25913,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.41, postcss@npm:^8.4.33, postcss@npm:^8.4.41": - version: 8.4.41 - resolution: "postcss@npm:8.4.41" +"postcss@npm:8.4.44, postcss@npm:^8.4.33, postcss@npm:^8.4.41": + version: 8.4.44 + resolution: "postcss@npm:8.4.44" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.1" source-map-js: "npm:^1.2.0" - checksum: 10/6e6176c2407eff60493ca60a706c6b7def20a722c3adda94ea1ece38345eb99964191336fd62b62652279cec6938e79e0b1e1d477142c8d3516e7a725a74ee37 + checksum: 10/aac7ed383fdcde9def6ed814ee03bc3de68b345e3f9bea414df2daca08185b6cfb4044fe9f67e1d9e886f29642373b34fd4fde5976204ca66a5481859afdcb7d languageName: node linkType: hard From 3acb43cf2eca4161d51b47180796f99e63d09ad7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:15:55 +0100 Subject: [PATCH 20/63] Update dependency @types/systemjs to v6.15.0 (#92876) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- packages/grafana-o11y-ds-frontend/package.json | 2 +- packages/grafana-runtime/package.json | 2 +- packages/grafana-sql/package.json | 2 +- yarn.lock | 16 ++++++++-------- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index b41c1e3f513..35d490ceb2f 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "@types/slate-plain-serializer": "0.7.5", "@types/slate-react": "0.22.9", "@types/swagger-ui-react": "4.18.3", - "@types/systemjs": "6.13.5", + "@types/systemjs": "6.15.0", "@types/testing-library__jest-dom": "5.14.9", "@types/tinycolor2": "1.4.6", "@types/uuid": "9.0.8", diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json index e77535ffac9..3c67fd0b8fd 100644 --- a/packages/grafana-o11y-ds-frontend/package.json +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -38,7 +38,7 @@ "@types/jest": "^29.5.4", "@types/node": "20.16.3", "@types/react": "18.3.3", - "@types/systemjs": "6.13.5", + "@types/systemjs": "6.15.0", "@types/testing-library__jest-dom": "5.14.9", "jest": "^29.6.4", "react": "18.2.0", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 23b649d8c66..bdd5979df1c 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -60,7 +60,7 @@ "@types/lodash": "4.17.7", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", - "@types/systemjs": "6.13.5", + "@types/systemjs": "6.15.0", "esbuild": "0.20.2", "lodash": "4.17.21", "react": "18.2.0", diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index bf0ae0494ac..707027f09ba 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -46,7 +46,7 @@ "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "@types/react-virtualized-auto-sizer": "1.0.4", - "@types/systemjs": "6.13.5", + "@types/systemjs": "6.15.0", "@types/testing-library__jest-dom": "5.14.9", "@types/uuid": "9.0.8", "jest": "^29.6.4", diff --git a/yarn.lock b/yarn.lock index 01b43249786..ad165654303 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3694,7 +3694,7 @@ __metadata: "@types/jest": "npm:^29.5.4" "@types/node": "npm:20.16.3" "@types/react": "npm:18.3.3" - "@types/systemjs": "npm:6.13.5" + "@types/systemjs": "npm:6.15.0" "@types/testing-library__jest-dom": "npm:5.14.9" jest: "npm:^29.6.4" react: "npm:18.2.0" @@ -3876,7 +3876,7 @@ __metadata: "@types/lodash": "npm:4.17.7" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" - "@types/systemjs": "npm:6.13.5" + "@types/systemjs": "npm:6.15.0" esbuild: "npm:0.20.2" history: "npm:4.10.1" lodash: "npm:4.17.21" @@ -3996,7 +3996,7 @@ __metadata: "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" "@types/react-virtualized-auto-sizer": "npm:1.0.4" - "@types/systemjs": "npm:6.13.5" + "@types/systemjs": "npm:6.15.0" "@types/testing-library__jest-dom": "npm:5.14.9" "@types/uuid": "npm:9.0.8" immutable: "npm:4.3.7" @@ -10427,10 +10427,10 @@ __metadata: languageName: node linkType: hard -"@types/systemjs@npm:6.13.5": - version: 6.13.5 - resolution: "@types/systemjs@npm:6.13.5" - checksum: 10/f514baebdffa4530f6daf65c07212edc9e8a7130b22df85217f926788ae87ddd77ccd29e8dde126bba7b669ef7a6575e84ddc5757e7e854ca51392200731f245 +"@types/systemjs@npm:6.15.0": + version: 6.15.0 + resolution: "@types/systemjs@npm:6.15.0" + checksum: 10/2a0aed8176ddf7041c6c1103c223557ec94161bfe861f4fc03f10e88e7979fddddfbee2173c506781669d1be54489856137bb349552eeb7dcd89ac3f65f332b8 languageName: node linkType: hard @@ -18603,7 +18603,7 @@ __metadata: "@types/slate-plain-serializer": "npm:0.7.5" "@types/slate-react": "npm:0.22.9" "@types/swagger-ui-react": "npm:4.18.3" - "@types/systemjs": "npm:6.13.5" + "@types/systemjs": "npm:6.15.0" "@types/testing-library__jest-dom": "npm:5.14.9" "@types/tinycolor2": "npm:1.4.6" "@types/uuid": "npm:9.0.8" From db579877bd08f0ac7aec13602cc4a864b7850c1e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:53:01 +0100 Subject: [PATCH 21/63] Update dependency eslint-plugin-import to v2.30.0 (#92878) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 88 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/yarn.lock b/yarn.lock index ad165654303..f4fd2d1d14b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6880,6 +6880,13 @@ __metadata: languageName: node linkType: hard +"@rtsao/scc@npm:^1.1.0": + version: 1.1.0 + resolution: "@rtsao/scc@npm:1.1.0" + checksum: 10/17d04adf404e04c1e61391ed97bca5117d4c2767a76ae3e879390d6dec7b317fcae68afbf9e98badee075d0b64fa60f287729c4942021b4d19cd01db77385c01 + languageName: node + linkType: hard + "@scena/dragscroll@npm:^1.4.0": version: 1.4.0 resolution: "@scena/dragscroll@npm:1.4.0" @@ -11879,7 +11886,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8": +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": version: 3.1.8 resolution: "array-includes@npm:3.1.8" dependencies: @@ -11921,16 +11928,17 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" +"array.prototype.findlastindex@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.1" - checksum: 10/063cbab8eeac3aa01f3e980eecb9a8c5d87723032b49f7f814ecc6d75c33c03c17e3f43a458127a62e16303cab412f95d6ad9dc7e0ae6d9dc27a9bb76c24df7a + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246 languageName: node linkType: hard @@ -16533,42 +16541,43 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" +"eslint-module-utils@npm:^2.9.0": + version: 2.9.0 + resolution: "eslint-module-utils@npm:2.9.0" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 10/a9a7ed93eb858092e3cdc797357d4ead2b3ea06959b0eada31ab13862d46a59eb064b9cb82302214232e547980ce33618c2992f6821138a4934e65710ed9cc29 + checksum: 10/13e001c96a6ce8d3d7ad6798c9b86351820c9c4a9abc5a152e84b838d7937a781471b0128ee690d18def226741fc96e8c5cff78c059bdcafe9ab8625777fcf2a languageName: node linkType: hard "eslint-plugin-import@npm:^2.26.0": - version: 2.29.1 - resolution: "eslint-plugin-import@npm:2.29.1" + version: 2.30.0 + resolution: "eslint-plugin-import@npm:2.30.0" dependencies: - array-includes: "npm:^3.1.7" - array.prototype.findlastindex: "npm:^1.2.3" + "@rtsao/scc": "npm:^1.1.0" + array-includes: "npm:^3.1.8" + array.prototype.findlastindex: "npm:^1.2.5" array.prototype.flat: "npm:^1.3.2" array.prototype.flatmap: "npm:^1.3.2" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.8.0" - hasown: "npm:^2.0.0" - is-core-module: "npm:^2.13.1" + eslint-module-utils: "npm:^2.9.0" + hasown: "npm:^2.0.2" + is-core-module: "npm:^2.15.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.7" - object.groupby: "npm:^1.0.1" - object.values: "npm:^1.1.7" + object.fromentries: "npm:^2.0.8" + object.groupby: "npm:^1.0.3" + object.values: "npm:^1.2.0" semver: "npm:^6.3.1" tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 10/5865f05c38552145423c535326ec9a7113ab2305c7614c8b896ff905cfabc859c8805cac21e979c9f6f742afa333e6f62f812eabf891a7e8f5f0b853a32593c1 + checksum: 10/a5f85dfe76e27286c28a01d137769726ce3f758bcc03aa6b6f9e18700a40a08f57239f82e07efcab763c4b03a02d425edcc29fbecf40aad0124286978c6bc63c languageName: node linkType: hard @@ -20012,12 +20021,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.5.0": + version: 2.15.1 + resolution: "is-core-module@npm:2.15.1" dependencies: - hasown: "npm:^2.0.0" - checksum: 10/d53bd0cc24b0a0351fb4b206ee3908f71b9bbf1c47e9c9e14e5f06d292af1663704d2abd7e67700d6487b2b7864e0d0f6f10a1edf1892864bdffcb197d1845a2 + hasown: "npm:^2.0.2" + checksum: 10/77316d5891d5743854bcef2cd2f24c5458fb69fbc9705c12ca17d54a2017a67d0693bbf1ba8c77af376c0eef6bf6d1b27a4ab08e4db4e69914c3789bdf2ceec5 languageName: node linkType: hard @@ -24517,7 +24526,7 @@ __metadata: languageName: node linkType: hard -"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8": +"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.8": version: 2.0.8 resolution: "object.fromentries@npm:2.0.8" dependencies: @@ -24529,15 +24538,14 @@ __metadata: languageName: node linkType: hard -"object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" +"object.groupby@npm:^1.0.3": + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - checksum: 10/b7123d91403f95d63978513b23a6079c30f503311f64035fafc863c291c787f287b58df3b21ef002ce1d0b820958c9009dd5a8ab696e0eca325639d345e41524 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + checksum: 10/44cb86dd2c660434be65f7585c54b62f0425b0c96b5c948d2756be253ef06737da7e68d7106e35506ce4a44d16aa85a413d11c5034eb7ce5579ec28752eb42d0 languageName: node linkType: hard @@ -24561,7 +24569,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0": +"object.values@npm:^1.1.6, object.values@npm:^1.2.0": version: 1.2.0 resolution: "object.values@npm:1.2.0" dependencies: From 5dce1492216fd3e620ad768cacb08597cd81a80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Philippe=20Qu=C3=A9m=C3=A9ner?= Date: Tue, 3 Sep 2024 18:01:27 +0200 Subject: [PATCH 22/63] feat(querier): propagate all known alerting headers (#92873) --- pkg/registry/apis/datasource/sub_query.go | 25 ++----------- .../apis/datasource/sub_query_test.go | 17 +++++++-- pkg/registry/apis/query/header_utils.go | 35 +++++++++++++++++++ pkg/registry/apis/query/query.go | 21 +---------- pkg/registry/apis/query/query_test.go | 18 +++++++--- 5 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 pkg/registry/apis/query/header_utils.go diff --git a/pkg/registry/apis/datasource/sub_query.go b/pkg/registry/apis/datasource/sub_query.go index 12747da51c4..6ab00ac5c78 100644 --- a/pkg/registry/apis/datasource/sub_query.go +++ b/pkg/registry/apis/datasource/sub_query.go @@ -4,14 +4,14 @@ import ( "context" "fmt" "net/http" - "strings" "github.com/grafana/grafana-plugin-sdk-go/backend" data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" + query "github.com/grafana/grafana/pkg/apis/query/v0alpha1" + query_headers "github.com/grafana/grafana/pkg/registry/apis/query" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/rest" - query "github.com/grafana/grafana/pkg/apis/query/v0alpha1" "github.com/grafana/grafana/pkg/web" ) @@ -74,29 +74,10 @@ func (r *subQueryREST) Connect(ctx context.Context, name string, opts runtime.Ob ctx = backend.WithGrafanaConfig(ctx, pluginCtx.GrafanaConfig) ctx = contextualMiddlewares(ctx) - // only forward expected headers, log unexpected ones - headers := make(map[string]string) - // headers are case insensitive, however some datasources still check for camel casing so we have to send them camel cased - expectedHeaders := map[string]string{ - "fromalert": "FromAlert", - "content-type": "Content-Type", - "content-length": "Content-Length", - "user-agent": "User-Agent", - "accept": "Accept", - } - for k, v := range req.Header { - headerToSend, ok := expectedHeaders[strings.ToLower(k)] - if ok { - headers[headerToSend] = v[0] - } else { - r.builder.log.Warn("datasource received an unexpected header, ignoring it", "header", k) - } - } - rsp, err := r.builder.client.QueryData(ctx, &backend.QueryDataRequest{ Queries: queries, PluginContext: pluginCtx, - Headers: headers, + Headers: query_headers.ExtractKnownHeaders(req.Header), }) if err != nil { responder.Error(err) diff --git a/pkg/registry/apis/datasource/sub_query_test.go b/pkg/registry/apis/datasource/sub_query_test.go index 22a683e1828..dc08c74afe4 100644 --- a/pkg/registry/apis/datasource/sub_query_test.go +++ b/pkg/registry/apis/datasource/sub_query_test.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/runtime" ) @@ -32,14 +33,24 @@ func TestSubQueryConnect(t *testing.T) { rr := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/some-path", nil) - req.Header.Set("fromAlert", "true") + req.Header.Set(models.FromAlertHeaderName, "true") + req.Header.Set(models.CacheSkipHeaderName, "true") + req.Header.Set("X-Rule-Uid", "abc") + req.Header.Set("X-Rule-Folder", "folder-1") + req.Header.Set("X-Rule-Source", "grafana-ruler") + req.Header.Set("X-Grafana-Org-Id", "1") req.Header.Set("Content-Type", "application/json") + req.Header.Set("some-unexpected-header", "some-value") handler.ServeHTTP(rr, req) // test that headers are forwarded and cased appropriately require.Equal(t, map[string]string{ - "FromAlert": "true", - "Content-Type": "application/json", + models.FromAlertHeaderName: "true", + models.CacheSkipHeaderName: "true", + "X-Rule-Uid": "abc", + "X-Rule-Folder": "folder-1", + "X-Rule-Source": "grafana-ruler", + "X-Grafana-Org-Id": "1", }, *sqr.builder.client.(mockClient).lastCalledWithHeaders) } diff --git a/pkg/registry/apis/query/header_utils.go b/pkg/registry/apis/query/header_utils.go new file mode 100644 index 00000000000..51389e04b3f --- /dev/null +++ b/pkg/registry/apis/query/header_utils.go @@ -0,0 +1,35 @@ +package query + +import ( + "net/http" + "strings" + + "github.com/grafana/grafana/pkg/services/ngalert/models" +) + +// Set of headers that we want to forward to the datasource api servers. Those are used i.e. for +// cache control or identifying the source of the request. +// +// The headers related to grafana alerting can be found here: +// https://github.com/grafana/grafana-ruler/blob/96e6d4b25c0d973a7615b92b35739511a6fbd72f/pkg/ruler/rulesmanager/ds_query_rule_evaluator.go#L313-L328 +// +// The usage of strings.ToLower is because the server would convert `FromAlert` to `Fromalert`. So the make matching +// easier, we just match all headers in lower case. +var expectedHeaders = map[string]string{ + strings.ToLower(models.FromAlertHeaderName): models.FromAlertHeaderName, + strings.ToLower(models.CacheSkipHeaderName): models.CacheSkipHeaderName, + strings.ToLower("X-Rule-Uid"): "X-Rule-Uid", + strings.ToLower("X-Rule-Folder"): "X-Rule-Folder", + strings.ToLower("X-Rule-Source"): "X-Rule-Source", + strings.ToLower("X-Grafana-Org-Id"): "X-Grafana-Org-Id", +} + +func ExtractKnownHeaders(header http.Header) map[string]string { + extractedHeaders := make(map[string]string) + for k, v := range header { + if headerName, exists := expectedHeaders[strings.ToLower(k)]; exists { + extractedHeaders[headerName] = v[0] + } + } + return extractedHeaders +} diff --git a/pkg/registry/apis/query/query.go b/pkg/registry/apis/query/query.go index f17943bee50..24482d1b889 100644 --- a/pkg/registry/apis/query/query.go +++ b/pkg/registry/apis/query/query.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" "strconv" - "strings" "time" "github.com/grafana/grafana-plugin-sdk-go/backend" @@ -135,26 +134,8 @@ func (r *queryREST) Connect(connectCtx context.Context, name string, _ runtime.O return } - // get headers from the original http req and add them to each sub request - // headers are case insensitive, however some datasources still check for camel casing so we have to send them camel cased - expectedHeaders := map[string]string{ - "fromalert": "FromAlert", - "content-type": "Content-Type", - "content-length": "Content-Length", - "user-agent": "User-Agent", - "accept": "Accept", - } - for i := range req.Requests { - req.Requests[i].Headers = make(map[string]string) - for k, v := range httpreq.Header { - headerToSend, ok := expectedHeaders[strings.ToLower(k)] - if ok { - req.Requests[i].Headers[headerToSend] = v[0] - } else { - b.log.Warn(fmt.Sprintf("query service received an unexpected header, ignoring it: %s", k)) - } - } + req.Requests[i].Headers = ExtractKnownHeaders(httpreq.Header) } // Actually run the query diff --git a/pkg/registry/apis/query/query_test.go b/pkg/registry/apis/query/query_test.go index f1bdde43fe3..35b45f9f210 100644 --- a/pkg/registry/apis/query/query_test.go +++ b/pkg/registry/apis/query/query_test.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/runtime" ) @@ -37,7 +38,7 @@ func TestQueryRestConnectHandler(t *testing.T) { rr := httptest.NewRecorder() body := runtime.RawExtension{ - Raw: []byte(`{ + Raw: []byte(`{ "queries": [ { "datasource": { @@ -53,14 +54,23 @@ func TestQueryRestConnectHandler(t *testing.T) { "to": "now"}`), } req := httptest.NewRequest(http.MethodGet, "/some-path", bytes.NewReader(body.Raw)) - req.Header.Set("fromAlert", "true") + req.Header.Set(models.FromAlertHeaderName, "true") + req.Header.Set(models.CacheSkipHeaderName, "true") + req.Header.Set("X-Rule-Uid", "abc") + req.Header.Set("X-Rule-Folder", "folder-1") + req.Header.Set("X-Rule-Source", "grafana-ruler") + req.Header.Set("X-Grafana-Org-Id", "1") req.Header.Set("Content-Type", "application/json") req.Header.Set("some-unexpected-header", "some-value") handler.ServeHTTP(rr, req) require.Equal(t, map[string]string{ - "FromAlert": "true", - "Content-Type": "application/json", + models.FromAlertHeaderName: "true", + models.CacheSkipHeaderName: "true", + "X-Rule-Uid": "abc", + "X-Rule-Folder": "folder-1", + "X-Rule-Source": "grafana-ruler", + "X-Grafana-Org-Id": "1", }, *b.client.(mockClient).lastCalledWithHeaders) } From 437472811e4399c18eea5ed1a88307b74e572215 Mon Sep 17 00:00:00 2001 From: Kyle Cunningham Date: Tue, 3 Sep 2024 15:27:14 -0500 Subject: [PATCH 23/63] Table: Fix nested table overlap when table is sorted (#92716) --- .betterer.results | 3 +-- .../grafana-ui/src/components/Table/RowsList.tsx | 7 +++++-- .../src/components/Table/TableCellInspector.tsx | 16 ++++++++++++---- public/locales/en-US/grafana.json | 1 + public/locales/pseudo-LOCALE/grafana.json | 1 + 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.betterer.results b/.betterer.results index 2f9307b0639..7dfcd646d68 100644 --- a/.betterer.results +++ b/.betterer.results @@ -835,8 +835,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "3"] ], "packages/grafana-ui/src/components/Table/TableCellInspector.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "1"] + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "packages/grafana-ui/src/components/Table/reducer.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], diff --git a/packages/grafana-ui/src/components/Table/RowsList.tsx b/packages/grafana-ui/src/components/Table/RowsList.tsx index 7e00eded5bb..4d3d7a1afb4 100644 --- a/packages/grafana-ui/src/components/Table/RowsList.tsx +++ b/packages/grafana-ui/src/components/Table/RowsList.tsx @@ -398,12 +398,15 @@ export const RowsList = (props: RowsListProps) => { } }; + // Key the virtualizer for expanded rows + const expandedKey = Object.keys(tableState.expanded).join('|'); + return ( <> void; mode: TableCellInspectorMode; @@ -28,11 +30,17 @@ export function TableCellInspector({ value, onDismiss, mode }: TableCellInspecto if (trimmedValue[0] === '{' || trimmedValue[0] === '[' || mode === 'code') { try { value = JSON.parse(value); - displayValue = JSON.stringify(value, null, ''); - } catch {} + displayValue = JSON.stringify(value, null, ' '); + } catch (error: any) { + // Display helpful error to help folks diagnose json errors + console.log( + 'Failed to parse JSON in Table cell inspector (this will cause JSON to not print nicely): ', + error.message + ); + } } } else { - displayValue = JSON.stringify(value, null, ''); + displayValue = JSON.stringify(value); } let text = displayValue; @@ -63,7 +71,7 @@ export function TableCellInspector({ value, onDismiss, mode }: TableCellInspecto text} style={{ marginLeft: 'auto', width: '200px' }}> - Copy to Clipboard + Copy to Clipboard {currentMode === 'code' ? ( Date: Tue, 3 Sep 2024 17:22:04 -0500 Subject: [PATCH 24/63] Templating: Fix searching non-latin template variables (#92789) --- .../pickers/OptionsPicker/reducer.test.ts | 41 +++++++++++++++++++ .../pickers/OptionsPicker/reducer.ts | 5 +++ 2 files changed, 46 insertions(+) diff --git a/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts b/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts index 24bfeb094a9..2b6a26cd0ce 100644 --- a/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts +++ b/public/app/features/variables/pickers/OptionsPicker/reducer.test.ts @@ -860,6 +860,47 @@ describe('optionsPickerReducer', () => { }); }); + describe('when searching non-latin chars', () => { + it('should skip fuzzy matching and fall back to substring', () => { + const searchQuery = '水'; + + const options: VariableOption[] = 'A水'.split(' ').map((v) => ({ + selected: false, + text: v, + value: v, + })); + + const expect: VariableOption[] = [ + { + selected: false, + text: '> ' + searchQuery, + value: searchQuery, + }, + ].concat( + 'A水'.split(' ').map((v) => ({ + selected: false, + text: v, + value: v, + })) + ); + + const { initialState } = getVariableTestContext({ + queryValue: searchQuery, + }); + + reducerTester() + .givenReducer(optionsPickerReducer, cloneDeep(initialState)) + .whenActionIsDispatched(updateOptionsAndFilter(options)) + .thenStateShouldEqual({ + ...cloneDeep(initialState), + options: expect, + selectedValues: [], + queryValue: searchQuery, + highlightIndex: 1, + }); + }); + }); + describe('when large data for updateOptionsFromSearch is dispatched and variable has searchFilter', () => { it('then state should be correct', () => { const searchQuery = '__searchFilter'; diff --git a/public/app/features/variables/pickers/OptionsPicker/reducer.ts b/public/app/features/variables/pickers/OptionsPicker/reducer.ts index 090517d800b..5525babc55b 100644 --- a/public/app/features/variables/pickers/OptionsPicker/reducer.ts +++ b/public/app/features/variables/pickers/OptionsPicker/reducer.ts @@ -8,6 +8,9 @@ import { applyStateChanges } from '../../../../core/utils/applyStateChanges'; import { ALL_VARIABLE_VALUE } from '../../constants'; import { isMulti, isQuery } from '../../guard'; +// https://catonmat.net/my-favorite-regex :) +const REGEXP_NON_ASCII = /[^ -~]/gm; + export interface ToggleOption { option?: VariableOption; forceSelect: boolean; @@ -251,6 +254,8 @@ const optionsPickerSlice = createSlice({ if (needle === '') { opts = action.payload; + } else if (REGEXP_NON_ASCII.test(needle)) { + opts = action.payload.filter((o) => o.text.includes(needle)); } else { // with current API, not seeing a way to cache this on state using action.payload's uniqueness // since it's recreated and includes selected state on each item :( From 4749064f5749378c267696225fcfadccd99a0ca2 Mon Sep 17 00:00:00 2001 From: brendamuir <100768211+brendamuir@users.noreply.github.com> Date: Wed, 4 Sep 2024 08:10:55 +0200 Subject: [PATCH 25/63] Alerting docs: responds to feedback on alerting state or error alerts (#92859) * Alerting docs: responds to feedback on alerting state or error alerts * ran prettier --- .../alerting/alerting-rules/create-grafana-managed-rule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md index af1d74c7294..b0e4cd732cd 100644 --- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md +++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md @@ -251,7 +251,7 @@ You can configure the alert instance state when its evaluation returns no data: | No Data configuration | Description | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | No Data | The default option. Sets alert instance state to `No data`.
The alert rule also creates a new alert instance `DatasourceNoData` with the name and UID of the alert rule, and UID of the datasource that returned no data as labels. | -| Alerting | Sets alert instance state to `Alerting`. It transitions from `Pending` to `Alerting` after the [pending period](ref:pending-period) has finished. | +| Alerting | Sets the alert instance state to `Pending` and then transitions to `Alerting` once the [pending period](ref:pending-period) ends. If you sent the pending period to 0, the alert instance state is immediately set to `Alerting`. | | Normal | Sets alert instance state to `Normal`. | | Keep Last State | Maintains the alert instance in its last state. Useful for mitigating temporary issues, refer to [Keep last state](ref:keep-last-state). | From 636b831d90f7176c5066f4a15f157f94c754a3e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:38:00 +0300 Subject: [PATCH 26/63] Update dependency knip to v5.29.2 (#92882) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f4fd2d1d14b..73e6a59e5d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21703,8 +21703,8 @@ __metadata: linkType: hard "knip@npm:^5.10.0": - version: 5.27.4 - resolution: "knip@npm:5.27.4" + version: 5.29.2 + resolution: "knip@npm:5.29.2" dependencies: "@nodelib/fs.walk": "npm:1.2.8" "@snyk/github-codeowners": "npm:1.1.0" @@ -21728,7 +21728,7 @@ __metadata: bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10/48daf6f44e6aefe4c7f9d0f611e202fcb78aa1ead48cfdebbb17bbebcd2b9db0a7bdb9024a6ee10dbe5bc521f9066ec76f2afb4fba9a7dc646a1fd62332bfb63 + checksum: 10/448958d719223eb854728afb9f41a19c652c20ea9d6944191e2560d3b93c6e395be6aa174915f0cd1389b207de65dff145d219fbdb898d70b82dd788f4718686 languageName: node linkType: hard From aec73f350135808bcd5e468c925d1399d17d306e Mon Sep 17 00:00:00 2001 From: Tom Ratcliffe Date: Wed, 4 Sep 2024 10:22:03 +0100 Subject: [PATCH 27/63] Alerting/Chore: Mock API (MSW) in browser (#89223) Co-authored-by: joshhunt --- .github/CODEOWNERS | 2 + .nxignore | 1 + .prettierignore | 3 + conf/defaults.ini | 3 + package.json | 5 + pkg/api/http_server.go | 7 + public/app/index.ts | 14 +- public/mockServiceWorker.js | 284 +++++++++++++++++++++++++++++++++ public/test/mock-api/worker.ts | 5 + 9 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 .nxignore create mode 100644 public/mockServiceWorker.js create mode 100644 public/test/mock-api/worker.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eeb90d4556a..cfc637c729b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -369,6 +369,7 @@ /package.json @grafana/frontend-ops /nx.json @grafana/frontend-ops /project.json @grafana/frontend-ops +/.nxignore @grafana/frontend-ops /tsconfig.json @grafana/frontend-ops /.editorconfig @grafana/frontend-ops /.eslintignore @grafana/frontend-ops @@ -501,6 +502,7 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/lib/ @grafana/grafana-frontend-platform /public/lib/monaco-languages/kusto.ts @grafana/partner-datasources /public/maps/ @ryantxu +/public/mockServiceWorker.js @grafana/frontend-ops /public/robots.txt @grafana/frontend-ops /public/fonts/ @grafana/grafana-frontend-platform /public/sass/ @grafana/grafana-frontend-platform diff --git a/.nxignore b/.nxignore new file mode 100644 index 00000000000..edf9f018d25 --- /dev/null +++ b/.nxignore @@ -0,0 +1 @@ +!conf/custom.ini diff --git a/.prettierignore b/.prettierignore index 76bf2adf696..8bf9dc13276 100644 --- a/.prettierignore +++ b/.prettierignore @@ -28,5 +28,8 @@ public/api-merged.json public/api-enterprise-spec.json public/openapi3.json +# Generated mock service worker +public/mockServiceWorker.js + # Crowdin files public/locales/**/*.json diff --git a/conf/defaults.ini b/conf/defaults.ini index e164bf0fbd2..49209a9ea69 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -1996,3 +1996,6 @@ frontend_poll_interval = 2s # Should UI tests fail when console log/warn/erroring? # Does not affect the result when running on CI - only for allowing devs to choose this behaviour locally fail_tests_on_console = true +# Whether or not to enable the MSW mock API, which intercepts requests and returns mock data +# Should only be used for local development or demo purposes +mock_api = false diff --git a/package.json b/package.json index 35d490ceb2f..f3ff5b5d176 100644 --- a/package.json +++ b/package.json @@ -445,5 +445,10 @@ "prettier@3.3.3": { "unplugged": true } + }, + "msw": { + "workerDirectory": [ + "public" + ] } } diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 9f5ac6b79fd..6f1295aa48f 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -604,6 +604,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() { hs.mapStatic(m, hs.Cfg.StaticRootPath, "build", "public/build") hs.mapStatic(m, hs.Cfg.StaticRootPath, "", "public", "/public/views/swagger.html") hs.mapStatic(m, hs.Cfg.StaticRootPath, "robots.txt", "robots.txt") + hs.mapStatic(m, hs.Cfg.StaticRootPath, "mockServiceWorker.js", "mockServiceWorker.js") if hs.Cfg.ImageUploadProvider == "local" { hs.mapStatic(m, hs.Cfg.ImagesDir, "", "/public/img/attachments") @@ -753,6 +754,12 @@ func (hs *HTTPServer) mapStatic(m *web.Mux, rootDir string, dir string, prefix s } } + if prefix == "mockServiceWorker.js" { + headers = func(c *web.Context) { + c.Resp.Header().Set("Content-Type", "application/javascript") + } + } + m.Use(httpstatic.Static( path.Join(rootDir, dir), httpstatic.StaticOptions{ diff --git a/public/app/index.ts b/public/app/index.ts index 6cbb37dfbec..cfbaee2e5cd 100644 --- a/public/app/index.ts +++ b/public/app/index.ts @@ -19,4 +19,16 @@ if (window.nonce) { window.__grafana_app_bundle_loaded = true; import app from './app'; -app.init(); + +const prepareInit = async () => { + if (process.env.frontend_dev_mock_api) { + return import('test/mock-api/worker').then((workerModule) => { + workerModule.default.start({ onUnhandledRequest: 'bypass' }); + }); + } + return Promise.resolve(); +}; + +prepareInit().then(() => { + app.init(); +}); diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js new file mode 100644 index 00000000000..15751fa1994 --- /dev/null +++ b/public/mockServiceWorker.js @@ -0,0 +1,284 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.3.5' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = crypto.randomUUID() + event.respondWith(handleRequest(event, requestId)) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const responseClone = response.clone() + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client?.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone() + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()) + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention'] + + return fetch(requestClone, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer() + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data) + } + + case 'PASSTHROUGH': { + return passthrough() + } + } + + return passthrough() +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage( + message, + [channel.port2].concat(transferrables.filter(Boolean)), + ) + }) +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error() + } + + const mockedResponse = new Response(response.body, response) + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }) + + return mockedResponse +} diff --git a/public/test/mock-api/worker.ts b/public/test/mock-api/worker.ts new file mode 100644 index 00000000000..350c842e2bd --- /dev/null +++ b/public/test/mock-api/worker.ts @@ -0,0 +1,5 @@ +import { setupWorker } from 'msw/browser'; + +import allAlertingHandlers from 'app/features/alerting/unified/mocks/server/all-handlers'; + +export default setupWorker(...allAlertingHandlers); From 7933cbd204b7d6ead3ad87095a76b35ce74bdaaf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 08:40:51 +0000 Subject: [PATCH 28/63] Update dependency @types/node to v20.16.4 --- package.json | 2 +- packages/grafana-data/package.json | 2 +- packages/grafana-e2e-selectors/package.json | 2 +- packages/grafana-flamegraph/package.json | 2 +- packages/grafana-icons/package.json | 2 +- .../grafana-o11y-ds-frontend/package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- packages/grafana-sql/package.json | 2 +- packages/grafana-ui/package.json | 2 +- .../datasource/azuremonitor/package.json | 2 +- .../datasource/cloud-monitoring/package.json | 2 +- .../package.json | 2 +- .../grafana-pyroscope-datasource/package.json | 2 +- .../grafana-testdata-datasource/package.json | 2 +- .../plugins/datasource/jaeger/package.json | 2 +- .../app/plugins/datasource/mssql/package.json | 2 +- .../app/plugins/datasource/mysql/package.json | 2 +- .../app/plugins/datasource/parca/package.json | 2 +- .../app/plugins/datasource/tempo/package.json | 2 +- .../plugins/datasource/zipkin/package.json | 2 +- yarn.lock | 48 +++++++++---------- 21 files changed, 44 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index f3ff5b5d176..bc3dbbe1371 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "@types/lodash": "4.17.7", "@types/logfmt": "^1.2.3", "@types/lucene": "^2", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/node-forge": "^1", "@types/ol-ext": "npm:@siedlerchr/types-ol-ext@3.2.4", "@types/pluralize": "^0.0.33", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 6c3f8d197d7..d04f8ffffe6 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -66,7 +66,7 @@ "@types/dompurify": "^3.0.0", "@types/history": "4.7.11", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/papaparse": "5.3.14", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 93c93582786..aedf497ad4d 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -40,7 +40,7 @@ }, "devDependencies": { "@rollup/plugin-node-resolve": "15.2.3", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "esbuild": "0.20.2", "rimraf": "5.0.7", "rollup": "2.79.1", diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index 70b54a6f5ab..54d88edad67 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -68,7 +68,7 @@ "@types/d3": "^7", "@types/jest": "^29.5.4", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-virtualized-auto-sizer": "1.0.4", "@types/tinycolor2": "1.4.6", diff --git a/packages/grafana-icons/package.json b/packages/grafana-icons/package.json index 195276ec300..a2ce757c97a 100644 --- a/packages/grafana-icons/package.json +++ b/packages/grafana-icons/package.json @@ -45,7 +45,7 @@ "@svgr/plugin-prettier": "^8.1.0", "@svgr/plugin-svgo": "^8.1.0", "@types/babel__core": "^7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "esbuild": "0.20.2", diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json index 3c67fd0b8fd..a6d517d8883 100644 --- a/packages/grafana-o11y-ds-frontend/package.json +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -36,7 +36,7 @@ "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", "@types/jest": "^29.5.4", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/systemjs": "6.15.0", "@types/testing-library__jest-dom": "5.14.9", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 1982895a0c8..3448df39526 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -92,7 +92,7 @@ "@types/jest": "29.5.12", "@types/jquery": "3.5.30", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/pluralize": "^0.0.33", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index 707027f09ba..fea6724e138 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -42,7 +42,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "^29.5.4", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "@types/react-virtualized-auto-sizer": "1.0.4", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 9693c2c1c0f..a5e66d110c8 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -145,7 +145,7 @@ "@types/is-hotkey": "0.1.10", "@types/jest": "29.5.12", "@types/mock-raf": "1.0.6", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", "@types/react-color": "3.0.12", diff --git a/public/app/plugins/datasource/azuremonitor/package.json b/public/app/plugins/datasource/azuremonitor/package.json index 32a78621bba..a0ee8fc110a 100644 --- a/public/app/plugins/datasource/azuremonitor/package.json +++ b/public/app/plugins/datasource/azuremonitor/package.json @@ -32,7 +32,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", diff --git a/public/app/plugins/datasource/cloud-monitoring/package.json b/public/app/plugins/datasource/cloud-monitoring/package.json index 922b16b0959..c08befb4d65 100644 --- a/public/app/plugins/datasource/cloud-monitoring/package.json +++ b/public/app/plugins/datasource/cloud-monitoring/package.json @@ -34,7 +34,7 @@ "@types/debounce-promise": "3.1.9", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json index 0bc2186eeb8..244d76e8c33 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json @@ -22,7 +22,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/testing-library__jest-dom": "5.14.9", "ts-node": "10.9.2", diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json index 583415ef850..1efd82e0515 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json @@ -27,7 +27,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/package.json b/public/app/plugins/datasource/grafana-testdata-datasource/package.json index cb974c6544d..16c9bcc304c 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/package.json +++ b/public/app/plugins/datasource/grafana-testdata-datasource/package.json @@ -30,7 +30,7 @@ "@types/d3-random": "^3.0.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "@types/testing-library__jest-dom": "5.14.9", diff --git a/public/app/plugins/datasource/jaeger/package.json b/public/app/plugins/datasource/jaeger/package.json index b498a1ecb3f..cf60fd93fb6 100644 --- a/public/app/plugins/datasource/jaeger/package.json +++ b/public/app/plugins/datasource/jaeger/package.json @@ -31,7 +31,7 @@ "@types/jest": "29.5.12", "@types/lodash": "4.17.7", "@types/logfmt": "^1.2.3", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "@types/react-window": "1.8.8", diff --git a/public/app/plugins/datasource/mssql/package.json b/public/app/plugins/datasource/mssql/package.json index 3ced516d4b7..c9fc0794200 100644 --- a/public/app/plugins/datasource/mssql/package.json +++ b/public/app/plugins/datasource/mssql/package.json @@ -22,7 +22,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/testing-library__jest-dom": "5.14.9", "ts-node": "10.9.2", diff --git a/public/app/plugins/datasource/mysql/package.json b/public/app/plugins/datasource/mysql/package.json index 9b625ba7f8d..3a893853055 100644 --- a/public/app/plugins/datasource/mysql/package.json +++ b/public/app/plugins/datasource/mysql/package.json @@ -22,7 +22,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/testing-library__jest-dom": "5.14.9", "ts-node": "10.9.2", diff --git a/public/app/plugins/datasource/parca/package.json b/public/app/plugins/datasource/parca/package.json index 350bedf7620..ab3591154b4 100644 --- a/public/app/plugins/datasource/parca/package.json +++ b/public/app/plugins/datasource/parca/package.json @@ -23,7 +23,7 @@ "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "ts-node": "10.9.2", diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index 06288f4f1b3..3f53d571866 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -46,7 +46,7 @@ "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/prismjs": "1.26.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", diff --git a/public/app/plugins/datasource/zipkin/package.json b/public/app/plugins/datasource/zipkin/package.json index e5167fac452..2f6cb826d41 100644 --- a/public/app/plugins/datasource/zipkin/package.json +++ b/public/app/plugins/datasource/zipkin/package.json @@ -25,7 +25,7 @@ "@testing-library/react": "15.0.2", "@types/jest": "29.5.12", "@types/lodash": "4.17.7", - "@types/node": "20.16.3", + "@types/node": "20.16.4", "@types/react": "18.3.3", "@types/react-dom": "18.2.25", "ts-node": "10.9.2", diff --git a/yarn.lock b/yarn.lock index 73e6a59e5d3..5ee3c1d1615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2935,7 +2935,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" @@ -2977,7 +2977,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/testing-library__jest-dom": "npm:5.14.9" lodash: "npm:4.17.21" @@ -3008,7 +3008,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" @@ -3051,7 +3051,7 @@ __metadata: "@types/d3-random": "npm:^3.0.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" "@types/testing-library__jest-dom": "npm:5.14.9" @@ -3093,7 +3093,7 @@ __metadata: "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" "@types/logfmt": "npm:^1.2.3" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" "@types/react-window": "npm:1.8.8" @@ -3132,7 +3132,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/testing-library__jest-dom": "npm:5.14.9" lodash: "npm:4.17.21" @@ -3163,7 +3163,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/testing-library__jest-dom": "npm:5.14.9" lodash: "npm:4.17.21" @@ -3192,7 +3192,7 @@ __metadata: "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" lodash: "npm:4.17.21" @@ -3229,7 +3229,7 @@ __metadata: "@types/debounce-promise": "npm:3.1.9" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" @@ -3285,7 +3285,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" @@ -3334,7 +3334,7 @@ __metadata: "@testing-library/react": "npm:15.0.2" "@types/jest": "npm:29.5.12" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" lodash: "npm:4.17.21" @@ -3392,7 +3392,7 @@ __metadata: "@types/dompurify": "npm:^3.0.0" "@types/history": "npm:4.7.11" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/papaparse": "npm:5.3.14" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" @@ -3439,7 +3439,7 @@ __metadata: dependencies: "@grafana/tsconfig": "npm:^2.0.0" "@rollup/plugin-node-resolve": "npm:15.2.3" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" esbuild: "npm:0.20.2" rimraf: "npm:5.0.7" rollup: "npm:2.79.1" @@ -3608,7 +3608,7 @@ __metadata: "@types/d3": "npm:^7" "@types/jest": "npm:^29.5.4" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-virtualized-auto-sizer": "npm:1.0.4" "@types/tinycolor2": "npm:1.4.6" @@ -3692,7 +3692,7 @@ __metadata: "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:^29.5.4" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/systemjs": "npm:6.15.0" "@types/testing-library__jest-dom": "npm:5.14.9" @@ -3780,7 +3780,7 @@ __metadata: "@types/jest": "npm:29.5.12" "@types/jquery": "npm:3.5.30" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/pluralize": "npm:^0.0.33" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" @@ -3912,7 +3912,7 @@ __metadata: "@svgr/plugin-prettier": "npm:^8.1.0" "@svgr/plugin-svgo": "npm:^8.1.0" "@types/babel__core": "npm:^7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" esbuild: "npm:0.20.2" @@ -3992,7 +3992,7 @@ __metadata: "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:^29.5.4" "@types/lodash": "npm:4.17.7" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.2.25" "@types/react-virtualized-auto-sizer": "npm:1.0.4" @@ -4086,7 +4086,7 @@ __metadata: "@types/jquery": "npm:3.5.30" "@types/lodash": "npm:4.17.7" "@types/mock-raf": "npm:1.0.6" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/prismjs": "npm:1.26.4" "@types/react": "npm:18.3.3" "@types/react-color": "npm:3.0.12" @@ -9984,12 +9984,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:20.16.3, @types/node@npm:>=13.7.0, @types/node@npm:^20.11.16": - version: 20.16.3 - resolution: "@types/node@npm:20.16.3" +"@types/node@npm:*, @types/node@npm:20.16.4, @types/node@npm:>=13.7.0, @types/node@npm:^20.11.16": + version: 20.16.4 + resolution: "@types/node@npm:20.16.4" dependencies: undici-types: "npm:~6.19.2" - checksum: 10/3b14b8b3cb92adc7db69f8cf351e7b6b5001e5c7cdb07470943215afeafc2952ae588c918543784e8f8e975d43d609ce0c7bced91f1b8745f1669d6137adaabc + checksum: 10/3c6ecc81ee77b67938004a0ffc7459ad9df242218a3eea8249036950262ba32061cfac0d7b74781d50cd9399bfd9b903c3b250caa2f4e76f526c4b55b929b670 languageName: node linkType: hard @@ -18588,7 +18588,7 @@ __metadata: "@types/lodash": "npm:4.17.7" "@types/logfmt": "npm:^1.2.3" "@types/lucene": "npm:^2" - "@types/node": "npm:20.16.3" + "@types/node": "npm:20.16.4" "@types/node-forge": "npm:^1" "@types/ol-ext": "npm:@siedlerchr/types-ol-ext@3.2.4" "@types/pluralize": "npm:^0.0.33" From 9d3d1703f7a33df32fcd3a456bc148260f115912 Mon Sep 17 00:00:00 2001 From: brendamuir <100768211+brendamuir@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:54:38 +0200 Subject: [PATCH 29/63] Alerting docs: adds caps not supported in email contact points (#92902) * Alerting docs: adds caps not supported in email contact points * ran prettier * feedback from antonio * ran prettier --- .../manage-contact-points/integrations/configure-email.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md index 8295288797b..81b6ccac4d8 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md @@ -75,6 +75,9 @@ To set up email integration, complete the following steps. 1. Enter a contact point name. 1. From the Integration list, select **Email**. 1. Enter the email addresses you want to send notifications to. + + E-mail addresses are case sensitive. Ensure that the e-mail address entered is correct. + 1. Click **Test** to check that your integration works. 1. Click **Save contact point**. From 9c837407bf56602983fd3ae42ac7a72fbb766ca2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:28:39 +0000 Subject: [PATCH 30/63] Update dependency eslint-plugin-react to v7.35.2 --- package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- yarn.lock | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index bc3dbbe1371..94cca56339e 100644 --- a/package.json +++ b/package.json @@ -181,7 +181,7 @@ "eslint-plugin-jsx-a11y": "6.9.0", "eslint-plugin-lodash": "7.4.0", "eslint-plugin-no-barrel-files": "^1.1.0", - "eslint-plugin-react": "7.35.1", + "eslint-plugin-react": "7.35.2", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-testing-library": "^6.2.2", "eslint-scope": "^8.0.0", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 3448df39526..6f8210879dc 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -114,7 +114,7 @@ "eslint-plugin-jsdoc": "48.11.0", "eslint-plugin-jsx-a11y": "6.9.0", "eslint-plugin-lodash": "7.4.0", - "eslint-plugin-react": "7.35.1", + "eslint-plugin-react": "7.35.2", "eslint-plugin-react-hooks": "4.6.0", "eslint-webpack-plugin": "4.2.0", "fork-ts-checker-webpack-plugin": "9.0.2", diff --git a/yarn.lock b/yarn.lock index 5ee3c1d1615..6e8efcd9342 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3805,7 +3805,7 @@ __metadata: eslint-plugin-jsdoc: "npm:48.11.0" eslint-plugin-jsx-a11y: "npm:6.9.0" eslint-plugin-lodash: "npm:7.4.0" - eslint-plugin-react: "npm:7.35.1" + eslint-plugin-react: "npm:7.35.2" eslint-plugin-react-hooks: "npm:4.6.0" eslint-webpack-plugin: "npm:4.2.0" eventemitter3: "npm:5.0.1" @@ -16736,9 +16736,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react@npm:7.35.1": - version: 7.35.1 - resolution: "eslint-plugin-react@npm:7.35.1" +"eslint-plugin-react@npm:7.35.2": + version: 7.35.2 + resolution: "eslint-plugin-react@npm:7.35.2" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -16760,7 +16760,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10/5bbae54dcef5a84bd71277315238d63caaa23effecd1a376b83ccf1cf033770ee44b763300f9fb55c569d7688ebc93d12728018dcfe240423c6059cc7284ba3f + checksum: 10/f4631612444f9066c8007e9433c0972754b75d33be410cd18dcf003e4209600240dec3e50a9962aae35e9a08920a1eb60e51d3cc140e5f6c95582e727ebec74e languageName: node linkType: hard @@ -18672,7 +18672,7 @@ __metadata: eslint-plugin-jsx-a11y: "npm:6.9.0" eslint-plugin-lodash: "npm:7.4.0" eslint-plugin-no-barrel-files: "npm:^1.1.0" - eslint-plugin-react: "npm:7.35.1" + eslint-plugin-react: "npm:7.35.2" eslint-plugin-react-hooks: "npm:4.6.0" eslint-plugin-testing-library: "npm:^6.2.2" eslint-scope: "npm:^8.0.0" From 14e1403b9ec0212d3935771067ffe900009ea62d Mon Sep 17 00:00:00 2001 From: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:02:06 +0200 Subject: [PATCH 31/63] Alerting: Recording rules detail view nits (#92643) * Hide some fields in the details tab (view page) when it's a grafana recording rule * link to the explore view from the metric name in the detail view * Revert "link to the explore view from the metric name in the detail view" This reverts commit 3c17d16cf633892ae080bd43f73f77c82b8d4fc9. * move logic to usePendingPeriod hook * move logic to getPendingPeriod function * move logic for getting annotations to a new getAnnotations function --- .../components/rule-viewer/tabs/Details.tsx | 12 +++++----- .../features/alerting/unified/utils/rules.ts | 23 ++++++++++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx index 53c74196586..9d9397f8839 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx @@ -5,10 +5,9 @@ import { useCallback } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { ClipboardButton, Stack, Text, TextLink, useStyles2 } from '@grafana/ui'; import { CombinedRule } from 'app/types/unified-alerting'; -import { Annotations } from 'app/types/unified-alerting-dto'; import { usePendingPeriod } from '../../../hooks/rules/usePendingPeriod'; -import { isGrafanaRulerRule, isRecordingRulerRule } from '../../../utils/rules'; +import { getAnnotations, isGrafanaRecordingRule, isGrafanaRulerRule, isRecordingRulerRule } from '../../../utils/rules'; import { MetaText } from '../../MetaText'; import { Tokenize } from '../../Tokenize'; @@ -18,6 +17,7 @@ interface DetailsProps { enum RuleType { GrafanaManagedAlertRule = 'Grafana-managed alert rule', + GrafanaManagedRecordingRule = 'Grafana-managed recording rule', CloudAlertRule = 'Cloud alert rule', CloudRecordingRule = 'Cloud recording rule', } @@ -30,7 +30,9 @@ const Details = ({ rule }: DetailsProps) => { const pendingPeriod = usePendingPeriod(rule); if (isGrafanaRulerRule(rule.rulerRule)) { - ruleType = RuleType.GrafanaManagedAlertRule; + ruleType = isGrafanaRecordingRule(rule.rulerRule) + ? RuleType.GrafanaManagedRecordingRule + : RuleType.GrafanaManagedAlertRule; } else if (isRecordingRulerRule(rule.rulerRule)) { ruleType = RuleType.CloudRecordingRule; } else { @@ -49,9 +51,7 @@ const Details = ({ rule }: DetailsProps) => { } }, [rule.rulerRule]); - const annotations: Annotations | undefined = !isRecordingRulerRule(rule.rulerRule) - ? (rule.annotations ?? []) - : undefined; + const annotations = getAnnotations(rule); const hasEvaluationDuration = Number.isFinite(evaluationDuration); diff --git a/public/app/features/alerting/unified/utils/rules.ts b/public/app/features/alerting/unified/utils/rules.ts index cc4a7af1af9..0a716dfe64f 100644 --- a/public/app/features/alerting/unified/utils/rules.ts +++ b/public/app/features/alerting/unified/utils/rules.ts @@ -9,6 +9,7 @@ import { CombinedRule, CombinedRuleGroup, CombinedRuleWithLocation, + EditableRuleIdentifier, GrafanaRuleIdentifier, PromRuleWithLocation, PrometheusRuleIdentifier, @@ -19,9 +20,9 @@ import { RuleNamespace, RuleWithLocation, RulesSource, - EditableRuleIdentifier, } from 'app/types/unified-alerting'; import { + Annotations, GrafanaAlertState, GrafanaAlertStateWithReason, PostableRuleDTO, @@ -81,10 +82,6 @@ export function isGrafanaRulerRule(rule?: RulerRuleDTO | PostableRuleDTO): rule return typeof rule === 'object' && 'grafana_alert' in rule; } -export function isGrafanaRecordingRulerRule(rule?: RulerRuleDTO) { - return typeof rule === 'object' && 'grafana_alert' in rule && 'record' in rule.grafana_alert; -} - export function isCloudRulerRule(rule?: RulerRuleDTO | PostableRuleDTO): rule is RulerCloudRuleDTO { return typeof rule === 'object' && !isGrafanaRulerRule(rule); } @@ -138,7 +135,11 @@ export function getRuleHealth(health: string): RuleHealth | undefined { } export function getPendingPeriod(rule: CombinedRule): string | undefined { - if (isRecordingRulerRule(rule.rulerRule) || isRecordingRule(rule.promRule)) { + if ( + isRecordingRulerRule(rule.rulerRule) || + isRecordingRule(rule.promRule) || + isGrafanaRecordingRule(rule.rulerRule) + ) { return undefined; } @@ -157,6 +158,16 @@ export function getPendingPeriod(rule: CombinedRule): string | undefined { return undefined; } +export function getAnnotations(rule: CombinedRule): Annotations | undefined { + if ( + isRecordingRulerRule(rule.rulerRule) || + isRecordingRule(rule.promRule) || + isGrafanaRecordingRule(rule.rulerRule) + ) { + return undefined; + } + return rule.annotations ?? []; +} export interface RulePluginOrigin { pluginId: string; } From 8daa6f1f30c77a215aeb143128a2ba705ca07c81 Mon Sep 17 00:00:00 2001 From: Andreas Christou Date: Wed, 4 Sep 2024 11:03:17 +0100 Subject: [PATCH 32/63] CI: Ensure changelogs are prettified prior to commit (#92580) * Ensure changelogs are prettified prior to commit * Remove cache property * Include .yarn directory * Include packages directory * Try just using npx * Update workflows --- .github/workflows/changelog.yml | 13 +++++++++++-- .github/workflows/release-pr.yml | 8 +++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index c0d2a24b0ac..d23ca18e612 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -74,8 +74,15 @@ jobs: sparse-checkout: | .github/workflows CHANGELOG.md + .nvmrc + .prettierignore + .prettierrc.js fetch-depth: 0 fetch-tags: true + - name: Setup nodejs environment + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc - name: "Configure git user" run: | git config --local user.name "github-actions[bot]" @@ -120,9 +127,11 @@ jobs: fi git diff CHANGELOG.md - git add CHANGELOG.md + + - name: "Prettify CHANGELOG.md" + run: npx prettier --write CHANGELOG.md - name: "Commit changelog changes" - run: git commit --allow-empty -m "Update changelog" CHANGELOG.md + run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md - name: "git push" if: ${{ inputs.dry_run }} != true run: git push diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 9304ca5301c..d6bcd7d5446 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -74,6 +74,10 @@ jobs: fetch-depth: '0' fetch-tags: 'false' path: .grafana-main + - name: Setup nodejs environment + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc - name: Configure git user run: | git config --local user.name "github-actions[bot]" @@ -120,7 +124,9 @@ jobs: rm -f CHANGELOG.part changelog_items.md git diff CHANGELOG.md - + + - name: "Prettify CHANGELOG.md" + run: npx prettier --write CHANGELOG.md - name: Commit CHANGELOG.md changes run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md From 13c8f4d2121985a4284aa36da909a5188b1eef71 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:59:39 +0000 Subject: [PATCH 33/63] Update dependency postcss to v8.4.45 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 94cca56339e..7b7763e58b2 100644 --- a/package.json +++ b/package.json @@ -210,7 +210,7 @@ "ngtemplate-loader": "2.1.0", "node-notifier": "10.0.1", "nx": "19.2.0", - "postcss": "8.4.44", + "postcss": "8.4.45", "postcss-loader": "8.1.1", "postcss-reporter": "7.1.0", "postcss-scss": "4.0.9", diff --git a/yarn.lock b/yarn.lock index 6e8efcd9342..fe7d8f1f913 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18735,7 +18735,7 @@ __metadata: ol: "npm:7.4.0" ol-ext: "npm:4.0.23" pluralize: "npm:^8.0.0" - postcss: "npm:8.4.44" + postcss: "npm:8.4.45" postcss-loader: "npm:8.1.1" postcss-reporter: "npm:7.1.0" postcss-scss: "npm:4.0.9" @@ -25921,14 +25921,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.44, postcss@npm:^8.4.33, postcss@npm:^8.4.41": - version: 8.4.44 - resolution: "postcss@npm:8.4.44" +"postcss@npm:8.4.45, postcss@npm:^8.4.33, postcss@npm:^8.4.41": + version: 8.4.45 + resolution: "postcss@npm:8.4.45" dependencies: nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.1" source-map-js: "npm:^1.2.0" - checksum: 10/aac7ed383fdcde9def6ed814ee03bc3de68b345e3f9bea414df2daca08185b6cfb4044fe9f67e1d9e886f29642373b34fd4fde5976204ca66a5481859afdcb7d + checksum: 10/7eaf7346d04929ee979548ece5e34d253eae6f175346e298b2c4621ad6f4ee00adfe7abe72688640e910c0361ae50537c5dda3e35fd1066491282c342b3ee5c8 languageName: node linkType: hard From b213ecc2dd15330119912330420d56f7b8179baa Mon Sep 17 00:00:00 2001 From: linoman <2051016+linoman@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:19:45 +0200 Subject: [PATCH 34/63] SSO LDAP: Add configuration for root ca, client key and client certificate (#92866) * Add missing properties with `_value` prefix * Add RadioButtonGrpoup * Add file/value section for certs * Add mapping for keys and certificates * Rename base and file types * Add styles * Add base64 values configuration flags * Add function to render root ca certificate contents * generate i18n files --- public/app/features/admin/ldap/LdapDrawer.tsx | 274 ++++++++++++++---- .../features/admin/ldap/LdapSettingsPage.tsx | 34 ++- public/app/types/ldap.ts | 12 + public/locales/en-US/grafana.json | 105 +++---- public/locales/pseudo-LOCALE/grafana.json | 105 +++---- 5 files changed, 352 insertions(+), 178 deletions(-) diff --git a/public/app/features/admin/ldap/LdapDrawer.tsx b/public/app/features/admin/ldap/LdapDrawer.tsx index eec47a0100d..53e1eb6a96f 100644 --- a/public/app/features/admin/ldap/LdapDrawer.tsx +++ b/public/app/features/admin/ldap/LdapDrawer.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import { useId } from 'react'; +import { Dispatch, SetStateAction, useEffect, useId, useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; @@ -12,25 +12,41 @@ import { Icon, Input, Label, + MultiSelect, Select, Stack, Switch, Text, TextLink, Tooltip, + RadioButtonGroup, + SecretInput, } from '@grafana/ui'; import { t, Trans } from 'app/core/internationalization'; -import { LdapPayload } from 'app/types'; +import { LdapPayload, MapKeyCertConfigured } from 'app/types'; interface Props { onClose: () => void; + mapKeyCertConfigured: MapKeyCertConfigured; + setMapKeyCertConfigured: Dispatch>; } +const serverConfig = 'settings.config.servers.0'; const tlsOptions: Array> = ['TLS1.2', 'TLS1.3'].map((v) => ({ label: v, value: v })); +enum EncryptionProvider { + Base64 = 'base64', + FilePath = 'path', +} + +export const LdapDrawerComponent = ({ + onClose, + mapKeyCertConfigured: mapCertConfigured, + setMapKeyCertConfigured: setMapCertConfigured, +}: Props) => { + const [encryptionProvider, setEncryptionProvider] = useState(EncryptionProvider.Base64); -export const LdapDrawerComponent = ({ onClose }: Props) => { const styles = useStyles2(getStyles); - const { register, setValue, watch } = useFormContext(); + const { getValues, register, setValue, watch } = useFormContext(); const nameId = useId(); const surnameId = useId(); @@ -38,6 +54,22 @@ export const LdapDrawerComponent = ({ onClose }: Props) => { const memberOfId = useId(); const emailId = useId(); + useEffect(() => { + const { client_cert, client_key, root_ca_cert } = getValues(serverConfig); + setEncryptionProvider( + !client_cert.length && !client_key.length && !root_ca_cert?.length + ? EncryptionProvider.Base64 + : EncryptionProvider.FilePath + ); + }, [getValues]); + + const renderMultiSelectLabel = (value: string) => { + if (value.length >= 5) { + return `${value.slice(0, 2)}...${value.slice(-2)}`; + } + return value; + }; + const groupMappingsLabel = (