From fe6503139a22ffbed8bfc28fd42ba7929d07e9ba Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Tue, 9 Jul 2024 16:56:32 +0200 Subject: [PATCH 1/2] Example: Add migration example --- .../pkg/kinds/query.go | 5 ++- .../pkg/kinds/query.panel.example.json | 2 +- .../pkg/kinds/query.panel.schema.json | 8 +++-- .../pkg/kinds/query.request.example.json | 2 +- .../pkg/kinds/query.request.schema.json | 8 +++-- .../pkg/kinds/query.types.json | 12 ++++--- .../pkg/kinds/query_test.go | 2 +- .../pkg/plugin/datasource.go | 6 ++-- .../src/components/QueryEditor.tsx | 35 +++++++++++-------- .../datasource-http-backend/src/datasource.ts | 23 ++++++++++-- examples/datasource-http-backend/src/types.ts | 10 ++++-- 11 files changed, 77 insertions(+), 36 deletions(-) diff --git a/examples/datasource-http-backend/pkg/kinds/query.go b/examples/datasource-http-backend/pkg/kinds/query.go index da5f1b8d5..cb16ab508 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.go +++ b/examples/datasource-http-backend/pkg/kinds/query.go @@ -6,7 +6,10 @@ import ( ) type DataQuery struct { - Multiplier int `json:"multiplier"` + // Deprecated: Moved to Multiply, made optional + Multiplier int `json:"multiplier,omitempty"` + // Multiply is the number to multiply the input by + Multiply int `json:"multiply,omitempty"` } //go:embed query.types.json diff --git a/examples/datasource-http-backend/pkg/kinds/query.panel.example.json b/examples/datasource-http-backend/pkg/kinds/query.panel.example.json index bbd4d4872..d19a2d88c 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.panel.example.json +++ b/examples/datasource-http-backend/pkg/kinds/query.panel.example.json @@ -7,7 +7,7 @@ "type": "grafana-testdata-datasource", "uid": "TheUID" }, - "multiplier": 1 + "multiply": 1 } ] } \ No newline at end of file diff --git a/examples/datasource-http-backend/pkg/kinds/query.panel.schema.json b/examples/datasource-http-backend/pkg/kinds/query.panel.schema.json index 4c951eec3..baafffb0d 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.panel.schema.json +++ b/examples/datasource-http-backend/pkg/kinds/query.panel.schema.json @@ -9,9 +9,6 @@ "type": "array", "items": { "type": "object", - "required": [ - "multiplier" - ], "properties": { "datasource": { "description": "The datasource", @@ -49,6 +46,11 @@ "type": "integer" }, "multiplier": { + "description": "Deprecated: Moved to Multiply, made optional", + "type": "integer" + }, + "multiply": { + "description": "Multiply is the number to multiply the input by", "type": "integer" }, "queryType": { diff --git a/examples/datasource-http-backend/pkg/kinds/query.request.example.json b/examples/datasource-http-backend/pkg/kinds/query.request.example.json index 04be906f1..dac1e1857 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.request.example.json +++ b/examples/datasource-http-backend/pkg/kinds/query.request.example.json @@ -6,7 +6,7 @@ "refId": "A", "maxDataPoints": 1000, "intervalMs": 5, - "multiplier": 1 + "multiply": 1 } ] } \ No newline at end of file diff --git a/examples/datasource-http-backend/pkg/kinds/query.request.schema.json b/examples/datasource-http-backend/pkg/kinds/query.request.schema.json index bd4bfe06a..bd4a971e9 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.request.schema.json +++ b/examples/datasource-http-backend/pkg/kinds/query.request.schema.json @@ -19,9 +19,6 @@ "type": "array", "items": { "type": "object", - "required": [ - "multiplier" - ], "properties": { "datasource": { "description": "The datasource", @@ -59,6 +56,11 @@ "type": "integer" }, "multiplier": { + "description": "Deprecated: Moved to Multiply, made optional", + "type": "integer" + }, + "multiply": { + "description": "Multiply is the number to multiply the input by", "type": "integer" }, "queryType": { diff --git a/examples/datasource-http-backend/pkg/kinds/query.types.json b/examples/datasource-http-backend/pkg/kinds/query.types.json index a59f668a7..8cd1b88d9 100644 --- a/examples/datasource-http-backend/pkg/kinds/query.types.json +++ b/examples/datasource-http-backend/pkg/kinds/query.types.json @@ -8,7 +8,7 @@ { "metadata": { "name": "default", - "resourceVersion": "1720173156947", + "resourceVersion": "1720430974503", "creationTimestamp": "2024-07-05T09:52:36Z" }, "spec": { @@ -17,19 +17,21 @@ "additionalProperties": false, "properties": { "multiplier": { + "description": "Deprecated: Moved to Multiply, made optional", + "type": "integer" + }, + "multiply": { + "description": "Multiply is the number to multiply the input by", "type": "integer" } }, - "required": [ - "multiplier" - ], "type": "object" }, "examples": [ { "name": "simple multiplier", "saveModel": { - "multiplier": 1 + "multiply": 1 } } ] diff --git a/examples/datasource-http-backend/pkg/kinds/query_test.go b/examples/datasource-http-backend/pkg/kinds/query_test.go index b2d81af5d..27687fef8 100644 --- a/examples/datasource-http-backend/pkg/kinds/query_test.go +++ b/examples/datasource-http-backend/pkg/kinds/query_test.go @@ -29,7 +29,7 @@ func TestQueryTypeDefinitions(t *testing.T) { Name: "simple multiplier", SaveModel: data.AsUnstructured( DataQuery{ - Multiplier: 1, + Multiply: 1, }, ), }, diff --git a/examples/datasource-http-backend/pkg/plugin/datasource.go b/examples/datasource-http-backend/pkg/plugin/datasource.go index 3dbb150c6..b75b6d316 100644 --- a/examples/datasource-http-backend/pkg/plugin/datasource.go +++ b/examples/datasource-http-backend/pkg/plugin/datasource.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + "github.com/grafana/datasource-http-backend/pkg/kinds" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" @@ -174,13 +175,14 @@ func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, quer return backend.DataResponse{}, fmt.Errorf("new request with context: %w", err) } if len(query.JSON) > 0 { - input := &apiQuery{} + input := &kinds.DataQuery{} err = json.Unmarshal(query.JSON, input) if err != nil { return backend.DataResponse{}, fmt.Errorf("unmarshal: %w", err) } q := req.URL.Query() - q.Add("multiplier", strconv.Itoa(input.Multiplier)) + // Temporarily use both + q.Add("multiplier", strconv.Itoa(input.Multiply)) req.URL.RawQuery = q.Encode() } httpResp, err := d.httpClient.Do(req) diff --git a/examples/datasource-http-backend/src/components/QueryEditor.tsx b/examples/datasource-http-backend/src/components/QueryEditor.tsx index 3cf13b0e4..36a03865d 100644 --- a/examples/datasource-http-backend/src/components/QueryEditor.tsx +++ b/examples/datasource-http-backend/src/components/QueryEditor.tsx @@ -1,4 +1,4 @@ -import React, { PureComponent } from 'react'; +import React, { useEffect, useState } from 'react'; import { QueryEditorProps } from '@grafana/data'; import { DataSource } from '../datasource'; import { MyDataSourceOptions, MyQuery } from '../types'; @@ -6,19 +6,24 @@ import { HorizontalGroup, Input, Label } from '@grafana/ui'; type Props = QueryEditorProps; -export class QueryEditor extends PureComponent { - render() { - return ( - - - this.props.onChange({ ...this.props.query, multiplier: e.currentTarget.valueAsNumber })} - /> - - ); +export function QueryEditor(props: Props) { + const [query, setQuery] = useState(); + useEffect(() => { + setQuery(props.datasource.migrateQuery(props.query)); + }, [props.query, props.datasource]); + if (!query) { + return 'loading...'; } + return ( + + + props.onChange({ ...query, multiply: e.currentTarget.valueAsNumber })} + /> + + ); } diff --git a/examples/datasource-http-backend/src/datasource.ts b/examples/datasource-http-backend/src/datasource.ts index 19d31d869..10ec9e5e0 100644 --- a/examples/datasource-http-backend/src/datasource.ts +++ b/examples/datasource-http-backend/src/datasource.ts @@ -1,7 +1,8 @@ import { CoreApp, DataSourceInstanceSettings } from '@grafana/data'; -import { MyQuery, MyDataSourceOptions } from './types'; +import { MyQuery, MyDataSourceOptions, MyQueryDeprecated } from './types'; import { DataSourceWithBackend } from '@grafana/runtime'; +import { omit } from 'lodash'; export class DataSource extends DataSourceWithBackend { constructor(instanceSettings: DataSourceInstanceSettings) { @@ -9,6 +10,24 @@ export class DataSource extends DataSourceWithBackend { - return { multiplier: 1 }; + return { multiply: 1 }; + } + + migrateQuery(query: MyQuery | MyQueryDeprecated): MyQuery { + if (query.datasource?.apiVersion !== 'v0alpha1') { + // Unkown version + return query as MyQuery; + } + if ('multiply' in query) { + return query; + } + if ('multiplier' in query) { + const migrated: MyQuery = { + ...query, + multiply: query.multiplier, + }; + return omit(migrated, 'multiplier'); + } + throw new Error('Unknown query format'); } } diff --git a/examples/datasource-http-backend/src/types.ts b/examples/datasource-http-backend/src/types.ts index 8c845f552..81ba313e5 100644 --- a/examples/datasource-http-backend/src/types.ts +++ b/examples/datasource-http-backend/src/types.ts @@ -1,9 +1,15 @@ -import { DataQuery, DataSourceJsonData } from '@grafana/data'; +import { DataQuery, DataSourceJsonData } from '@grafana/schema'; -export interface MyQuery extends DataQuery { +export interface MyQueryDeprecated extends DataQuery { + // Old implementation multiplier: number; } +export interface MyQuery extends DataQuery { + // New + multiply: number; +} + /** * Value that is used in the backend, but never sent over HTTP to the frontend */ From 6a04b7d829736fa4810b63f66251882105b656ff Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Wed, 10 Jul 2024 13:12:54 +0200 Subject: [PATCH 2/2] minor changes --- .../datasource-http-backend/pkg/plugin/datasource.go | 1 - .../src/components/QueryEditor.tsx | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/examples/datasource-http-backend/pkg/plugin/datasource.go b/examples/datasource-http-backend/pkg/plugin/datasource.go index b75b6d316..fe883e9fb 100644 --- a/examples/datasource-http-backend/pkg/plugin/datasource.go +++ b/examples/datasource-http-backend/pkg/plugin/datasource.go @@ -181,7 +181,6 @@ func (d *Datasource) query(ctx context.Context, pCtx backend.PluginContext, quer return backend.DataResponse{}, fmt.Errorf("unmarshal: %w", err) } q := req.URL.Query() - // Temporarily use both q.Add("multiplier", strconv.Itoa(input.Multiply)) req.URL.RawQuery = q.Encode() } diff --git a/examples/datasource-http-backend/src/components/QueryEditor.tsx b/examples/datasource-http-backend/src/components/QueryEditor.tsx index 36a03865d..17e85697e 100644 --- a/examples/datasource-http-backend/src/components/QueryEditor.tsx +++ b/examples/datasource-http-backend/src/components/QueryEditor.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { QueryEditorProps } from '@grafana/data'; import { DataSource } from '../datasource'; import { MyDataSourceOptions, MyQuery } from '../types'; @@ -7,13 +7,7 @@ import { HorizontalGroup, Input, Label } from '@grafana/ui'; type Props = QueryEditorProps; export function QueryEditor(props: Props) { - const [query, setQuery] = useState(); - useEffect(() => { - setQuery(props.datasource.migrateQuery(props.query)); - }, [props.query, props.datasource]); - if (!query) { - return 'loading...'; - } + const query = props.datasource.migrateQuery(props.query); return (