Correlations: Allow target UID to be nullable for PATCH removal (#124166)

* backend changes

* frontend changes
This commit is contained in:
Kristina 2026-05-07 07:55:06 -05:00 committed by GitHub
parent a040cfab4c
commit 7e4643ab27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 38 additions and 14 deletions

View file

@ -13,7 +13,7 @@ correlationsv0alpha1: {
spec: {
type: CorrelationType
source: DataSourceRef
target?: DataSourceRef
target?: DataSourceRef | null // null is for PATCH/edit when we want to clear the value
description?: string
label: string
config: ConfigSpec

View file

@ -79,12 +79,13 @@ func (CorrelationTransformationSpec) OpenAPIModelName() string {
// +k8s:openapi-gen=true
type CorrelationSpec struct {
Type CorrelationCorrelationType `json:"type"`
Source CorrelationDataSourceRef `json:"source"`
Target *CorrelationDataSourceRef `json:"target,omitempty"`
Description *string `json:"description,omitempty"`
Label string `json:"label"`
Config CorrelationConfigSpec `json:"config"`
Type CorrelationCorrelationType `json:"type"`
Source CorrelationDataSourceRef `json:"source"`
// null is for PATCH/edit when we want to clear the value
Target *CorrelationDataSourceRef `json:"target,omitempty"`
Description *string `json:"description,omitempty"`
Label string `json:"label"`
Config CorrelationConfigSpec `json:"config"`
}
// NewCorrelationSpec creates a new CorrelationSpec object.

View file

@ -20,7 +20,7 @@ import (
)
var (
rawSchemaCorrelationv0alpha1 = []byte(`{"ConfigSpec":{"additionalProperties":false,"description":"there was a deprecated field here called type, we will need to move that for conversion and provisioning","properties":{"field":{"type":"string"},"target":{"$ref":"#/components/schemas/TargetSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationSpec"},"type":"array"}},"required":["field","target"],"type":"object"},"Correlation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"CorrelationType":{"enum":["query","external"],"type":"string"},"DataSourceRef":{"additionalProperties":false,"properties":{"group":{"description":"same as pluginId","type":"string"},"name":{"description":"same as grafana uid","type":"string"}},"required":["group","name"],"type":"object"},"TargetSpec":{"additionalProperties":true,"type":"object"},"TransformationSpec":{"additionalProperties":false,"properties":{"expression":{"type":"string"},"field":{"type":"string"},"mapValue":{"type":"string"},"type":{"enum":["regex","logfmt"],"type":"string"}},"required":["type"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/ConfigSpec"},"description":{"type":"string"},"label":{"type":"string"},"source":{"$ref":"#/components/schemas/DataSourceRef"},"target":{"$ref":"#/components/schemas/DataSourceRef"},"type":{"$ref":"#/components/schemas/CorrelationType"}},"required":["type","source","label","config"],"type":"object"}}`)
rawSchemaCorrelationv0alpha1 = []byte(`{"ConfigSpec":{"additionalProperties":false,"description":"there was a deprecated field here called type, we will need to move that for conversion and provisioning","properties":{"field":{"type":"string"},"target":{"$ref":"#/components/schemas/TargetSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationSpec"},"type":"array"}},"required":["field","target"],"type":"object"},"Correlation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"CorrelationType":{"enum":["query","external"],"type":"string"},"DataSourceRef":{"additionalProperties":false,"properties":{"group":{"description":"same as pluginId","type":"string"},"name":{"description":"same as grafana uid","type":"string"}},"required":["group","name"],"type":"object"},"TargetSpec":{"additionalProperties":true,"type":"object"},"TransformationSpec":{"additionalProperties":false,"properties":{"expression":{"type":"string"},"field":{"type":"string"},"mapValue":{"type":"string"},"type":{"enum":["regex","logfmt"],"type":"string"}},"required":["type"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"config":{"$ref":"#/components/schemas/ConfigSpec"},"description":{"type":"string"},"label":{"type":"string"},"source":{"$ref":"#/components/schemas/DataSourceRef"},"target":{"allOf":[{"$ref":"#/components/schemas/DataSourceRef"}],"description":"null is for PATCH/edit when we want to clear the value","nullable":true},"type":{"$ref":"#/components/schemas/CorrelationType"}},"required":["type","source","label","config"],"type":"object"}}`)
versionSchemaCorrelationv0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaCorrelationv0alpha1, &versionSchemaCorrelationv0alpha1)
)

View file

@ -86,6 +86,8 @@ func DataSourceMutator() *simple.Mutator {
c.Labels[TargetRefLabelKey] = fmt.Sprintf("%s.%s",
c.Spec.Target.Group,
c.Spec.Target.Name)
} else {
delete(c.Labels, TargetRefLabelKey)
}
return &app.MutatingResponse{UpdatedObject: c}, nil

View file

@ -49,7 +49,8 @@ export const defaultTransformationSpec = (): TransformationSpec => ({
export interface Spec {
type: CorrelationType;
source: DataSourceRef;
target?: DataSourceRef;
// null is for PATCH/edit when we want to clear the value
target?: DataSourceRef | null;
description?: string;
label: string;
config: ConfigSpec;

View file

@ -380,7 +380,8 @@ export type CorrelationSpec = {
description?: string;
label: string;
source: CorrelationDataSourceRef;
target?: CorrelationDataSourceRef;
/** null is for PATCH/edit when we want to clear the value */
target?: CorrelationDataSourceRef | null;
type: CorrelationCorrelationType;
};
export type Correlation = {

View file

@ -742,7 +742,13 @@
"$ref": "#/components/schemas/CorrelationDataSourceRef"
},
"target": {
"$ref": "#/components/schemas/CorrelationDataSourceRef"
"description": "null is for PATCH/edit when we want to clear the value",
"nullable": true,
"allOf": [
{
"$ref": "#/components/schemas/CorrelationDataSourceRef"
}
]
},
"type": {
"$ref": "#/components/schemas/CorrelationCorrelationType"

View file

@ -798,7 +798,13 @@
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.correlations.pkg.apis.correlation.v0alpha1.CorrelationDataSourceRef"
},
"target": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.correlations.pkg.apis.correlation.v0alpha1.CorrelationDataSourceRef"
"description": "null is for PATCH/edit when we want to clear the value",
"nullable": true,
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.correlations.pkg.apis.correlation.v0alpha1.CorrelationDataSourceRef"
}
]
},
"type": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.correlations.pkg.apis.correlation.v0alpha1.CorrelationCorrelationType"

View file

@ -141,7 +141,7 @@ describe('correlations utils', () => {
config.featureToggles.lokiLogsDataplane = originalDataplaneState;
});
it('generates a partial spec with config only when nothing is edited', () => {
it('generates a partial spec with config and nulled target only when nothing is edited and the correlation is external', () => {
const correlation: Correlation = {
uid: 'test',
sourceUID: 'test',
@ -152,7 +152,7 @@ describe('correlations utils', () => {
};
const editForm: EditFormDTO = { ...correlation, label: correlation.label! };
const partialSpec = generatePartialEditSpec(editForm, correlation);
expect(partialSpec).toStrictEqual({ config: { field: 'test', target: { url: 'test' } } });
expect(partialSpec).toStrictEqual({ config: { field: 'test', target: { url: 'test' } }, target: null });
});
it('generates a partial spec as expected when things are edited', () => {

View file

@ -150,6 +150,13 @@ export const generateDefaultLabel = async (sourcePane: ExploreItemState, targetP
export const generatePartialEditSpec = (data: EditFormDTO, correlation: Correlation): Partial<CorrelationSpec> => {
let partialSpec: Partial<CorrelationSpec> = {};
// we will want to clear any target data if the correlation is being updated to external
// null sent in a PATCH will delete the property
if (data.type === 'external') {
partialSpec.target = null;
}
if (data.label !== correlation.label) {
partialSpec.label = data.label;
}