full coverage for convert
This commit is contained in:
@@ -1484,6 +1484,7 @@ github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o=
|
||||
github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw=
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"iter"
|
||||
"maps"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -24,11 +25,16 @@ import (
|
||||
|
||||
type converter struct {
|
||||
mapper request.NamespaceMapper
|
||||
group string // the expected group
|
||||
dstype string // the expected pluginId
|
||||
group string // the expected group
|
||||
plugin string // the expected pluginId
|
||||
alias []string // optional alias for the pluginId
|
||||
}
|
||||
|
||||
func (r *converter) asDataSource(ds *datasources.DataSource) (*datasourceV0.DataSource, error) {
|
||||
if !(ds.Type == r.plugin || slices.Contains(r.alias, ds.Type)) {
|
||||
return nil, fmt.Errorf("expected datasource type: %s %v // not: %s", r.plugin, r.alias, ds.Type)
|
||||
}
|
||||
|
||||
obj := &datasourceV0.DataSource{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ds.UID,
|
||||
@@ -109,7 +115,7 @@ func (r *converter) toAddCommand(ds *datasourceV0.DataSource) (*datasources.AddD
|
||||
Name: ds.Spec.Title(),
|
||||
UID: ds.Name,
|
||||
OrgID: info.OrgID,
|
||||
Type: r.dstype,
|
||||
Type: r.plugin,
|
||||
|
||||
Access: datasources.DsAccess(ds.Spec.Access()),
|
||||
URL: ds.Spec.URL(),
|
||||
@@ -127,8 +133,8 @@ func (r *converter) toAddCommand(ds *datasourceV0.DataSource) (*datasources.AddD
|
||||
cmd.JsonData = simplejson.NewFromAny(jsonData)
|
||||
}
|
||||
|
||||
cmd.SecureJsonData, err = toSecureJsonData(ds)
|
||||
return cmd, err
|
||||
cmd.SecureJsonData = toSecureJsonData(ds)
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
func (r *converter) toUpdateCommand(ds *datasourceV0.DataSource) (*datasources.UpdateDataSourceCommand, error) {
|
||||
@@ -144,7 +150,7 @@ func (r *converter) toUpdateCommand(ds *datasourceV0.DataSource) (*datasources.U
|
||||
Name: ds.Spec.Title(),
|
||||
UID: ds.Name,
|
||||
OrgID: info.OrgID,
|
||||
Type: r.dstype,
|
||||
Type: r.plugin,
|
||||
|
||||
Access: datasources.DsAccess(ds.Spec.Access()),
|
||||
URL: ds.Spec.URL(),
|
||||
@@ -164,13 +170,13 @@ func (r *converter) toUpdateCommand(ds *datasourceV0.DataSource) (*datasources.U
|
||||
if jsonData != nil {
|
||||
cmd.JsonData = simplejson.NewFromAny(jsonData)
|
||||
}
|
||||
cmd.SecureJsonData, err = toSecureJsonData(ds)
|
||||
cmd.SecureJsonData = toSecureJsonData(ds)
|
||||
return cmd, err
|
||||
}
|
||||
|
||||
func toSecureJsonData(ds *datasourceV0.DataSource) (map[string]string, error) {
|
||||
func toSecureJsonData(ds *datasourceV0.DataSource) map[string]string {
|
||||
if ds == nil || len(ds.Secure) < 1 {
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
secure := map[string]string{}
|
||||
@@ -182,5 +188,5 @@ func toSecureJsonData(ds *datasourceV0.DataSource) (map[string]string, error) {
|
||||
secure[k] = "" // Weirdly, this is the best we can do with the legacy API :(
|
||||
}
|
||||
}
|
||||
return secure, nil
|
||||
return secure
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package datasource
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -18,24 +19,41 @@ func TestConverter(t *testing.T) {
|
||||
t.Run("resource to command", func(t *testing.T) {
|
||||
converter := converter{
|
||||
mapper: types.OrgNamespaceFormatter,
|
||||
dstype: "test-datasource",
|
||||
plugin: "grafana-testdata-datasource",
|
||||
alias: []string{"testdata"},
|
||||
group: "testdata.grafana.datasource.app",
|
||||
}
|
||||
check := []string{
|
||||
"convert-resource-A",
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedErr string
|
||||
}{
|
||||
{"convert-resource-full", ""},
|
||||
{"convert-resource-empty", ""},
|
||||
{"convert-resource-invalid", "expecting APIGroup: testdata.grafana.datasource.app"},
|
||||
{"convert-resource-invalid2", "invalid stack id"},
|
||||
}
|
||||
for _, name := range check {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
obj := &v0alpha1.DataSource{}
|
||||
fpath := filepath.Join("testdata", name+".json")
|
||||
fpath := filepath.Join("testdata", tt.name+".json")
|
||||
raw, err := os.ReadFile(fpath) // nolint:gosec
|
||||
require.NoError(t, err)
|
||||
err = json.Unmarshal(raw, obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
// The add command
|
||||
fpath = filepath.Join("testdata", name+"-to-cmd-add.json")
|
||||
fpath = filepath.Join("testdata", tt.name+"-to-cmd-add.json")
|
||||
add, err := converter.toAddCommand(obj)
|
||||
if tt.expectedErr != "" {
|
||||
require.ErrorContains(t, err, tt.expectedErr)
|
||||
require.Nil(t, add, "cmd should be nil when error exists")
|
||||
|
||||
update, err := converter.toUpdateCommand(obj)
|
||||
require.ErrorContains(t, err, tt.expectedErr)
|
||||
require.Nil(t, update, "cmd should be nil when error exists")
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
out, err := json.MarshalIndent(add, "", " ")
|
||||
require.NoError(t, err)
|
||||
@@ -45,9 +63,10 @@ func TestConverter(t *testing.T) {
|
||||
}
|
||||
|
||||
// The update command
|
||||
fpath = filepath.Join("testdata", name+"-to-cmd-update.json")
|
||||
fpath = filepath.Join("testdata", tt.name+"-to-cmd-update.json")
|
||||
update, err := converter.toUpdateCommand(obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
out, err = json.MarshalIndent(update, "", " ")
|
||||
require.NoError(t, err)
|
||||
raw, _ = os.ReadFile(fpath) // nolint:gosec
|
||||
@@ -63,7 +82,7 @@ func TestConverter(t *testing.T) {
|
||||
roundtrip, err := converter.asDataSource(ds)
|
||||
require.NoError(t, err)
|
||||
|
||||
fpath = filepath.Join("testdata", name+"-to-cmd-update-roundtrip.json")
|
||||
fpath = filepath.Join("testdata", tt.name+"-to-cmd-update-roundtrip.json")
|
||||
out, err = json.MarshalIndent(roundtrip, "", " ")
|
||||
require.NoError(t, err)
|
||||
raw, _ = os.ReadFile(fpath) // nolint:gosec
|
||||
@@ -74,41 +93,59 @@ func TestConverter(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("db to resource", func(t *testing.T) {
|
||||
t.Run("dto to resource", func(t *testing.T) {
|
||||
converter := converter{
|
||||
mapper: types.OrgNamespaceFormatter,
|
||||
dstype: "test-datasource",
|
||||
plugin: "grafana-testdata-datasource",
|
||||
alias: []string{"testdata"},
|
||||
group: "testdata.grafana.datasource.app",
|
||||
}
|
||||
check := []string{
|
||||
"convert-db-B",
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "convert-dto-testdata",
|
||||
},
|
||||
{
|
||||
name: "convert-dto-empty",
|
||||
},
|
||||
{
|
||||
name: "convert-dto-invalid",
|
||||
expectedErr: "expected datasource type: grafana-testdata-datasource [testdata]",
|
||||
},
|
||||
}
|
||||
for _, name := range check {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ds := &datasources.DataSource{}
|
||||
fpath := filepath.Join("testdata", name+".json")
|
||||
fpath := filepath.Join("testdata", tt.name+".json")
|
||||
raw, err := os.ReadFile(fpath) // nolint:gosec
|
||||
require.NoError(t, err)
|
||||
err = json.Unmarshal(raw, ds)
|
||||
require.NoError(t, err)
|
||||
|
||||
// if true {
|
||||
// ds.Created = time.Unix(100000000, 0).UTC()
|
||||
// ds.Updated = time.Unix(500000000, 0).UTC()
|
||||
// out, _ := json.MarshalIndent(ds, "", " ")
|
||||
// fmt.Printf("%s\n", string(out))
|
||||
// t.FailNow()
|
||||
// }
|
||||
|
||||
// As an object
|
||||
fpath = filepath.Join("testdata", name+"-to-resource.json")
|
||||
obj, err := converter.asDataSource(ds)
|
||||
require.NoError(t, err)
|
||||
out, err := json.MarshalIndent(obj, "", " ")
|
||||
require.NoError(t, err)
|
||||
raw, _ = os.ReadFile(fpath) // nolint:gosec
|
||||
if !assert.JSONEq(t, string(raw), string(out)) {
|
||||
_ = os.WriteFile(fpath, out, 0600)
|
||||
if tt.expectedErr != "" {
|
||||
require.ErrorContains(t, err, tt.expectedErr)
|
||||
require.Nil(t, obj, "object should be nil when error exists")
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Verify the result
|
||||
fpath = filepath.Join("testdata", tt.name+"-to-resource.json")
|
||||
if obj == nil {
|
||||
_, err := os.Stat(fpath)
|
||||
require.Error(t, err, "file should not exist")
|
||||
require.True(t, errors.Is(err, os.ErrNotExist))
|
||||
} else {
|
||||
out, err := json.MarshalIndent(obj, "", " ")
|
||||
require.NoError(t, err)
|
||||
raw, _ = os.ReadFile(fpath) // nolint:gosec
|
||||
if !assert.JSONEq(t, string(raw), string(out)) {
|
||||
_ = os.WriteFile(fpath, out, 0600)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ func (q *cachingDatasourceProvider) GetDatasourceProvider(pluginJson plugins.JSO
|
||||
contextProvider: q.contextProvider,
|
||||
converter: &converter{
|
||||
mapper: q.converter.mapper,
|
||||
dstype: pluginJson.ID,
|
||||
plugin: pluginJson.ID,
|
||||
alias: pluginJson.AliasIDs,
|
||||
group: group,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/plugins/httpresponsesender"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "unique-identifier",
|
||||
"namespace": "org-0",
|
||||
"uid": "YpaSG5GQAdxtLZtF6BqQWCeYXOhbVi5C4Cg4oILnJC0X",
|
||||
"generation": 8,
|
||||
"creationTimestamp": "2002-03-04T01:00:00Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "456"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"jsonData": null,
|
||||
"title": "Display name"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"id": 456,
|
||||
"version": 8,
|
||||
"name": "Display name",
|
||||
"uid": "unique-identifier",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"created": "2002-03-04T01:00:00Z"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"id": 456,
|
||||
"version": 8,
|
||||
"name": "Hello",
|
||||
"uid": "unique-identifier",
|
||||
"type": "not-valid-plugin",
|
||||
"created": "2002-03-04T01:00:00Z"
|
||||
}
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"secure": {
|
||||
"password": {
|
||||
"name": "ds-c429ac622e"
|
||||
"name": "ds-d5c1b093af"
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"version": 2,
|
||||
"name": "Hello",
|
||||
"uid": "unique-identifier",
|
||||
"type": "grafana-test-datasource",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"access": "proxy",
|
||||
"url": "http://something/",
|
||||
"user": "A",
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Hello testdata",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"access": "",
|
||||
"url": "",
|
||||
"user": "",
|
||||
"database": "",
|
||||
"basicAuth": false,
|
||||
"basicAuthUser": "",
|
||||
"withCredentials": false,
|
||||
"isDefault": false,
|
||||
"jsonData": null,
|
||||
"secureJsonData": null,
|
||||
"uid": "cejobd88i85j4d"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "cejobd88i85j4d",
|
||||
"namespace": "org-0",
|
||||
"uid": "boDNh7zU3nXj46rOXIJI7r44qaxjs8yy9I9dOj1MyBoX",
|
||||
"creationTimestamp": null
|
||||
},
|
||||
"spec": {
|
||||
"jsonData": null,
|
||||
"title": "Hello testdata"
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Hello testdata",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"access": "",
|
||||
"url": "",
|
||||
"user": "",
|
||||
"database": "",
|
||||
"basicAuth": false,
|
||||
"basicAuthUser": "",
|
||||
"withCredentials": false,
|
||||
"isDefault": false,
|
||||
"jsonData": null,
|
||||
"secureJsonData": null,
|
||||
"uid": "cejobd88i85j4d",
|
||||
"version": 0
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "cejobd88i85j4d"
|
||||
},
|
||||
"spec": {
|
||||
"title": "Hello testdata"
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Hello testdata",
|
||||
"type": "test-datasource",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"access": "proxy",
|
||||
"url": "http://something/",
|
||||
"user": "",
|
||||
@@ -15,6 +15,7 @@
|
||||
"ccc": 1.234
|
||||
},
|
||||
"secureJsonData": {
|
||||
"extra": "",
|
||||
"password": "XXXX"
|
||||
},
|
||||
"uid": "cejobd88i85j4d"
|
||||
+4
-1
@@ -22,8 +22,11 @@
|
||||
"withCredentials": true
|
||||
},
|
||||
"secure": {
|
||||
"extra": {
|
||||
"name": "ds-bb8b5d8b32"
|
||||
},
|
||||
"password": {
|
||||
"name": "ds-fdb9f6717d"
|
||||
"name": "ds-973a1eb29d"
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Hello testdata",
|
||||
"type": "test-datasource",
|
||||
"type": "grafana-testdata-datasource",
|
||||
"access": "proxy",
|
||||
"url": "http://something/",
|
||||
"user": "",
|
||||
@@ -15,6 +15,7 @@
|
||||
"ccc": 1.234
|
||||
},
|
||||
"secureJsonData": {
|
||||
"extra": "",
|
||||
"password": "XXXX"
|
||||
},
|
||||
"uid": "cejobd88i85j4d",
|
||||
+2
-1
@@ -27,6 +27,7 @@
|
||||
}
|
||||
},
|
||||
"secure": {
|
||||
"password": { "create": "XXXX" }
|
||||
"password": { "create": "XXXX" },
|
||||
"extra": { "remove": true }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"apiVersion": "something/else",
|
||||
"metadata": {
|
||||
"name": "cejobd88i85j4d",
|
||||
"namespace": "default",
|
||||
"uid": "IGIUtEQS21DtLpBG2rSGfuDoUX8cwsGrtb5aXauYeA4X",
|
||||
"resourceVersion": "1745320815000",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-04-22T11:20:11Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "12345"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"title": "Hello testdata"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "cejobd88i85j4d",
|
||||
"namespace": "stacks-invalid"
|
||||
},
|
||||
"spec": {
|
||||
"title": "Hello testdata"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user