Correlations: Make correlations work with provisioning

This commit is contained in:
Elfo404 2022-06-30 18:17:43 +01:00
parent 14b3043c28
commit eb9affc7e3
No known key found for this signature in database
GPG Key ID: 586539D9491F0726
6 changed files with 127 additions and 1 deletions

View File

@ -247,6 +247,13 @@ datasources:
access: proxy
url: http://localhost:3100
editable: false
correlations:
- targetUid: gdev-jaeger
label: "Jaeger traces"
description: "Related traces stored in Jaeger"
- targetUid: gdev-zipkin
label: "Zipkin traces"
description: "Related traces stored in Zipkin"
jsonData:
manageAlerts: false
derivedFields:

View File

@ -101,6 +101,7 @@ type AddDataSourceCommand struct {
BasicAuthUser string `json:"basicAuthUser"`
WithCredentials bool `json:"withCredentials"`
IsDefault bool `json:"isDefault"`
Correlations []Correlation `json:"-"`
JsonData *simplejson.Json `json:"jsonData"`
SecureJsonData map[string]string `json:"secureJsonData"`
Uid string `json:"uid"`
@ -126,6 +127,7 @@ type UpdateDataSourceCommand struct {
BasicAuthUser string `json:"basicAuthUser"`
WithCredentials bool `json:"withCredentials"`
IsDefault bool `json:"isDefault"`
Correlations []Correlation `json:"correlations"`
JsonData *simplejson.Json `json:"jsonData"`
SecureJsonData map[string]string `json:"secureJsonData"`
Version int `json:"version"`

View File

@ -42,6 +42,7 @@ type upsertDataSourceFromConfig struct {
BasicAuthUser string
WithCredentials bool
IsDefault bool
Correlations []datasources.Correlation
JSONData map[string]interface{}
SecureJSONData map[string]string
Editable bool
@ -86,6 +87,7 @@ type upsertDataSourceFromConfigV0 struct {
BasicAuthUser string `json:"basic_auth_user" yaml:"basic_auth_user"`
WithCredentials bool `json:"with_credentials" yaml:"with_credentials"`
IsDefault bool `json:"is_default" yaml:"is_default"`
Correlations []interface{} `json:"correlations" yaml:"correlations"`
JSONData map[string]interface{} `json:"json_data" yaml:"json_data"`
SecureJSONData map[string]string `json:"secure_json_data" yaml:"secure_json_data"`
Editable bool `json:"editable" yaml:"editable"`
@ -104,6 +106,7 @@ type upsertDataSourceFromConfigV1 struct {
BasicAuthUser values.StringValue `json:"basicAuthUser" yaml:"basicAuthUser"`
WithCredentials values.BoolValue `json:"withCredentials" yaml:"withCredentials"`
IsDefault values.BoolValue `json:"isDefault" yaml:"isDefault"`
Correlations values.JSONSliceValue `json:"correlations" yaml:"correlations"`
JSONData values.JSONValue `json:"jsonData" yaml:"jsonData"`
SecureJSONData values.StringMapValue `json:"secureJsonData" yaml:"secureJsonData"`
Editable values.BoolValue `json:"editable" yaml:"editable"`
@ -120,6 +123,19 @@ func (cfg *configsV1) mapToDatasourceFromConfig(apiVersion int64) *configs {
}
for _, ds := range cfg.Datasources {
correlations := make([]datasources.Correlation, 0)
for _, v := range ds.Correlations.Value() {
field, ok := v.(map[string]interface{})
if ok {
correlations = append(correlations, datasources.Correlation{
Target: field["targetUid"].(string),
Description: field["description"].(string),
Label: field["label"].(string),
})
}
}
r.Datasources = append(r.Datasources, &upsertDataSourceFromConfig{
OrgID: ds.OrgID.Value(),
Name: ds.Name.Value(),
@ -132,6 +148,7 @@ func (cfg *configsV1) mapToDatasourceFromConfig(apiVersion int64) *configs {
BasicAuthUser: ds.BasicAuthUser.Value(),
WithCredentials: ds.WithCredentials.Value(),
IsDefault: ds.IsDefault.Value(),
Correlations: correlations,
JSONData: ds.JSONData.Value(),
SecureJSONData: ds.SecureJSONData.Value(),
Editable: ds.Editable.Value(),
@ -160,6 +177,19 @@ func (cfg *configsV0) mapToDatasourceFromConfig(apiVersion int64) *configs {
}
for _, ds := range cfg.Datasources {
correlations := make([]datasources.Correlation, 0)
for _, v := range ds.Correlations {
field, ok := v.(map[string]interface{})
if ok {
correlations = append(correlations, datasources.Correlation{
Target: field["targetUid"].(string),
Description: field["description"].(string),
Label: field["label"].(string),
})
}
}
r.Datasources = append(r.Datasources, &upsertDataSourceFromConfig{
OrgID: ds.OrgID,
Name: ds.Name,
@ -172,6 +202,7 @@ func (cfg *configsV0) mapToDatasourceFromConfig(apiVersion int64) *configs {
BasicAuthUser: ds.BasicAuthUser,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
Correlations: correlations,
JSONData: ds.JSONData,
SecureJSONData: ds.SecureJSONData,
Editable: ds.Editable,
@ -209,6 +240,7 @@ func createInsertCommand(ds *upsertDataSourceFromConfig) *datasources.AddDataSou
BasicAuthUser: ds.BasicAuthUser,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
Correlations: ds.Correlations,
JsonData: jsonData,
SecureJsonData: ds.SecureJSONData,
ReadOnly: !ds.Editable,
@ -250,6 +282,7 @@ func createUpdateCommand(ds *upsertDataSourceFromConfig, id int64) *datasources.
BasicAuthUser: ds.BasicAuthUser,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
Correlations: ds.Correlations,
JsonData: jsonData,
SecureJsonData: ds.SecureJSONData,
ReadOnly: !ds.Editable,

View File

@ -188,6 +188,40 @@ func (val *StringMapValue) Value() map[string]string {
return val.value
}
// JSONSliceValue represents a slice value in a YAML
// config that can be overridden by environment variables
type JSONSliceValue struct {
value []interface{}
Raw []interface{}
}
// UnmarshalYAML converts YAML into an *JSONSliceValue
func (val *JSONSliceValue) UnmarshalYAML(unmarshal func(interface{}) error) error {
unmarshaled := make([]interface{}, 0)
err := unmarshal(&unmarshaled)
if err != nil {
return err
}
for _, v := range unmarshaled {
interpolated, raw, err := transformInterface(v)
if err != nil {
return err
}
val.value = append(val.value, interpolated)
val.Raw = append(val.Raw, raw)
}
return err
}
// Value returns the wrapped []interface{} value
func (val *JSONSliceValue) Value() []interface{} {
return val.value
}
// transformInterface tries to transform any interface type into proper value with env expansion. It traverses maps and
// slices and the actual interpolation is done on all simple string values in the structure. It returns a copy of any
// map or slice value instead of modifying them in place and also return value without interpolation but with converted

View File

@ -220,6 +220,55 @@ func TestValues(t *testing.T) {
})
})
t.Run("JSONSliceValue", func(t *testing.T) {
type Data struct {
Val JSONSliceValue `yaml:"val"`
}
d := &Data{}
t.Run("Should unmarshal top-level slices and nested structures", func(t *testing.T) {
doc := `
val:
- $STRING
- $INT
- stringMap:
interpolatedString: $STRING
interpolatedInt: $INT
string: "just a string"
sameLevel: $STRING
`
unmarshalingTest(t, doc, d)
type stringMap = map[string]interface{}
require.Equal(t, []interface{}{
"test",
"1",
stringMap{
"stringMap": stringMap{
"interpolatedString": "test",
"interpolatedInt": "1",
"string": "just a string",
},
"sameLevel": "test",
},
}, d.Val.Value())
require.Equal(t, []interface{}{
"$STRING",
"$INT",
stringMap{
"stringMap": stringMap{
"interpolatedString": "$STRING",
"interpolatedInt": "$INT",
"string": "just a string",
},
"sameLevel": "$STRING",
},
}, d.Val.Raw)
})
})
t.Run("StringMapValue", func(t *testing.T) {
type Data struct {
Val StringMapValue `yaml:"val"`

View File

@ -169,6 +169,7 @@ func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *datasources.AddDataS
BasicAuth: cmd.BasicAuth,
BasicAuthUser: cmd.BasicAuthUser,
WithCredentials: cmd.WithCredentials,
Correlations: cmd.Correlations,
JsonData: cmd.JsonData,
SecureJsonData: cmd.EncryptedSecureJsonData,
Created: time.Now(),
@ -303,7 +304,7 @@ func (ss *SQLStore) UpdateCorrelations(ctx context.Context, cmd *datasources.Upd
}
if affected == 0 {
return datasources.ErrDataSourceUpdatingOldVersion
return datasources.ErrDataSourceNotFound
}
cmd.Result = cmd.Correlations