Correlations: Add legacy storage (#112038)
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
package correlations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
authlib "github.com/grafana/authlib/types"
|
||||
correlationsV0 "github.com/grafana/grafana/apps/correlations/pkg/apis/correlation/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
)
|
||||
|
||||
func ToResource(orig Correlation, namespacer authlib.NamespaceFormatter) (*correlationsV0.Correlation, error) {
|
||||
cfg, err := ToSpecConfig(orig.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj := &correlationsV0.Correlation{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: orig.UID,
|
||||
Namespace: namespacer(orig.OrgID),
|
||||
},
|
||||
Spec: correlationsV0.CorrelationSpec{
|
||||
Label: orig.Label,
|
||||
Type: correlationsV0.CorrelationCorrelationType(orig.Type),
|
||||
Source: correlationsV0.CorrelationDataSourceRef{
|
||||
Group: ptr.Deref(orig.SourceType, ""),
|
||||
Name: orig.SourceUID,
|
||||
},
|
||||
Config: *cfg,
|
||||
},
|
||||
}
|
||||
if orig.TargetUID != nil {
|
||||
obj.Spec.Target = &correlationsV0.CorrelationDataSourceRef{
|
||||
Group: ptr.Deref(orig.TargetType, ""),
|
||||
Name: *orig.TargetUID,
|
||||
}
|
||||
}
|
||||
if orig.Description != "" {
|
||||
obj.Spec.Description = &orig.Description
|
||||
}
|
||||
if orig.Provisioned {
|
||||
tmp, _ := utils.MetaAccessor(obj)
|
||||
tmp.SetManagerProperties(utils.ManagerProperties{
|
||||
Kind: utils.ManagerKindClassicFP, // nolint:staticcheck
|
||||
})
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func ToCorrelation(obj *correlationsV0.Correlation) (*Correlation, error) {
|
||||
ns, err := authlib.ParseNamespace(obj.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg, err := ToConfig(obj.Spec.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &Correlation{
|
||||
UID: obj.Name,
|
||||
OrgID: ns.OrgID,
|
||||
Label: obj.Spec.Label,
|
||||
Description: ptr.Deref(obj.Spec.Description, ""),
|
||||
SourceUID: obj.Spec.Source.Name,
|
||||
SourceType: ptr.To(obj.Spec.Source.Group),
|
||||
Type: CorrelationType(obj.Spec.Type),
|
||||
Config: *cfg,
|
||||
}
|
||||
if obj.Annotations[utils.AnnoKeyManagerKind] != "" {
|
||||
result.Provisioned = true
|
||||
}
|
||||
if obj.Spec.Target != nil {
|
||||
result.TargetUID = &obj.Spec.Target.Name
|
||||
result.TargetType = ptr.To(obj.Spec.Target.Group)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func ToSpecConfig(orig CorrelationConfig) (*correlationsV0.CorrelationConfigSpec, error) {
|
||||
out := &correlationsV0.CorrelationConfigSpec{}
|
||||
raw, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(raw, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(out.Target) == 0 {
|
||||
out.Target = nil
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
func ToConfig(orig correlationsV0.CorrelationConfigSpec) (*CorrelationConfig, error) {
|
||||
out := &CorrelationConfig{}
|
||||
raw, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(raw, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(out.Target) == 0 {
|
||||
out.Target = nil
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
func ToUpdateCorrelationCommand(obj *correlationsV0.Correlation) (*UpdateCorrelationCommand, error) {
|
||||
tmp, err := ToCorrelation(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tmp.Config.Target == nil {
|
||||
tmp.Config.Target = map[string]any{} // replace it
|
||||
}
|
||||
return &UpdateCorrelationCommand{
|
||||
UID: tmp.UID,
|
||||
OrgId: tmp.OrgID,
|
||||
SourceUID: tmp.SourceUID,
|
||||
Label: &tmp.Label,
|
||||
Description: &tmp.Description,
|
||||
Type: &tmp.Type,
|
||||
Config: &CorrelationConfigUpdateDTO{
|
||||
Field: &tmp.Config.Field,
|
||||
Target: &tmp.Config.Target,
|
||||
Transformations: tmp.Config.Transformations,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ToCreateCorrelationCommand(obj *correlationsV0.Correlation) (*CreateCorrelationCommand, error) {
|
||||
tmp, err := ToCorrelation(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &CreateCorrelationCommand{
|
||||
OrgId: tmp.OrgID,
|
||||
SourceUID: tmp.SourceUID,
|
||||
TargetUID: tmp.TargetUID,
|
||||
Label: tmp.Label,
|
||||
Description: tmp.Description,
|
||||
Config: tmp.Config,
|
||||
Type: tmp.Type,
|
||||
Provisioned: tmp.Provisioned,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package correlations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
authlib "github.com/grafana/authlib/types"
|
||||
correlationsV0 "github.com/grafana/grafana/apps/correlations/pkg/apis/correlation/v0alpha1"
|
||||
)
|
||||
|
||||
func TestConversion(t *testing.T) {
|
||||
namespacer := authlib.OrgNamespaceFormatter
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input Correlation
|
||||
expect correlationsV0.Correlation
|
||||
create CreateCorrelationCommand
|
||||
update UpdateCorrelationCommand
|
||||
}{
|
||||
{
|
||||
name: "Basic fields",
|
||||
input: Correlation{
|
||||
UID: "uid",
|
||||
OrgID: 2,
|
||||
Label: "Test Label",
|
||||
Type: query,
|
||||
SourceUID: "source",
|
||||
SourceType: ptr.To("source-type"),
|
||||
TargetUID: ptr.To("target"),
|
||||
TargetType: ptr.To("target-type"),
|
||||
Description: "A test correlation",
|
||||
Provisioned: true,
|
||||
Config: CorrelationConfig{
|
||||
Field: "test-field",
|
||||
},
|
||||
},
|
||||
expect: correlationsV0.Correlation{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "uid",
|
||||
Namespace: "org-2",
|
||||
Annotations: map[string]string{
|
||||
"grafana.app/managedBy": "classic-file-provisioning",
|
||||
},
|
||||
},
|
||||
Spec: correlationsV0.CorrelationSpec{
|
||||
Description: ptr.To("A test correlation"),
|
||||
Label: "Test Label",
|
||||
Type: correlationsV0.CorrelationCorrelationTypeQuery,
|
||||
Source: correlationsV0.CorrelationDataSourceRef{
|
||||
Group: "source-type",
|
||||
Name: "source",
|
||||
},
|
||||
Target: &correlationsV0.CorrelationDataSourceRef{
|
||||
Group: "target-type",
|
||||
Name: "target",
|
||||
},
|
||||
Config: correlationsV0.CorrelationConfigSpec{
|
||||
Field: "test-field",
|
||||
},
|
||||
},
|
||||
},
|
||||
create: CreateCorrelationCommand{
|
||||
OrgId: 2,
|
||||
Label: "Test Label",
|
||||
Type: query,
|
||||
SourceUID: "source",
|
||||
TargetUID: ptr.To("target"),
|
||||
Description: "A test correlation",
|
||||
Provisioned: true,
|
||||
Config: CorrelationConfig{
|
||||
Field: "test-field",
|
||||
},
|
||||
},
|
||||
update: UpdateCorrelationCommand{
|
||||
UID: "uid",
|
||||
OrgId: 2,
|
||||
Label: ptr.To("Test Label"),
|
||||
Type: ptr.To(query),
|
||||
SourceUID: "source",
|
||||
Description: ptr.To("A test correlation"),
|
||||
Config: &CorrelationConfigUpdateDTO{
|
||||
Field: ptr.To("test-field"),
|
||||
Target: &map[string]any{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
res, err := ToResource(tt.input, namespacer)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &tt.expect, res, "conversion")
|
||||
|
||||
roundtrip, err := ToCorrelation(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &tt.input, roundtrip, "roundtrip")
|
||||
|
||||
create, err := ToCreateCorrelationCommand(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &tt.create, create, "create")
|
||||
|
||||
update, err := ToUpdateCorrelationCommand(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &tt.update, update, "update")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,10 @@ func ProvideService(sqlStore db.DB, routeRegister routing.RouteRegister, ds data
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
GetCorrelation(ctx context.Context, cmd GetCorrelationQuery) (Correlation, error)
|
||||
GetCorrelations(ctx context.Context, cmd GetCorrelationsQuery) (GetCorrelationsResponseBody, error)
|
||||
CreateCorrelation(ctx context.Context, cmd CreateCorrelationCommand) (Correlation, error)
|
||||
UpdateCorrelation(ctx context.Context, cmd UpdateCorrelationCommand) (Correlation, error)
|
||||
CreateOrUpdateCorrelation(ctx context.Context, cmd CreateCorrelationCommand) error
|
||||
DeleteCorrelation(ctx context.Context, cmd DeleteCorrelationCommand) error
|
||||
DeleteCorrelationsBySourceUID(ctx context.Context, cmd DeleteCorrelationsBySourceUIDCommand) error
|
||||
|
||||
@@ -54,7 +54,7 @@ func (s CorrelationsService) createCorrelation(ctx context.Context, cmd CreateCo
|
||||
}
|
||||
}
|
||||
|
||||
_, err = session.Insert(correlation)
|
||||
_, err = session.Omit("source_type", "target_type").Insert(correlation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -121,13 +121,13 @@ func (s CorrelationsService) updateCorrelation(ctx context.Context, cmd UpdateCo
|
||||
return ErrSourceDataSourceDoesNotExists
|
||||
}
|
||||
|
||||
found, err := session.Get(&correlation)
|
||||
if !found {
|
||||
return ErrCorrelationNotFound
|
||||
}
|
||||
found, err := session.Omit("source_type", "target_type").Get(&correlation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
return ErrCorrelationNotFound
|
||||
}
|
||||
if correlation.Provisioned {
|
||||
return ErrCorrelationReadOnly
|
||||
}
|
||||
@@ -156,7 +156,11 @@ func (s CorrelationsService) updateCorrelation(ctx context.Context, cmd UpdateCo
|
||||
}
|
||||
}
|
||||
|
||||
updateCount, err := session.Where("uid = ? AND source_uid = ?", correlation.UID, correlation.SourceUID).Limit(1).Update(correlation)
|
||||
updateCount, err := session.
|
||||
Where("uid = ? AND source_uid = ?", correlation.UID, correlation.SourceUID).
|
||||
Limit(1).
|
||||
Omit("source_type", "target_type").
|
||||
Update(correlation)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -179,20 +183,31 @@ func (s CorrelationsService) updateCorrelation(ctx context.Context, cmd UpdateCo
|
||||
func (s CorrelationsService) getCorrelation(ctx context.Context, cmd GetCorrelationQuery) (Correlation, error) {
|
||||
correlation := Correlation{
|
||||
UID: cmd.UID,
|
||||
OrgID: cmd.OrgId,
|
||||
SourceUID: cmd.SourceUID,
|
||||
}
|
||||
|
||||
err := s.SQLStore.WithTransactionalDbSession(ctx, func(session *db.Session) error {
|
||||
query := &datasources.GetDataSourceQuery{
|
||||
if cmd.SourceUID != "" {
|
||||
if _, err := s.DataSourceService.GetDataSource(ctx, &datasources.GetDataSourceQuery{
|
||||
UID: correlation.SourceUID,
|
||||
OrgID: cmd.OrgId,
|
||||
UID: cmd.SourceUID,
|
||||
}
|
||||
if _, err := s.DataSourceService.GetDataSource(ctx, query); err != nil {
|
||||
return ErrSourceDataSourceDoesNotExists
|
||||
}); err != nil {
|
||||
return Correlation{}, ErrSourceDataSourceDoesNotExists
|
||||
}
|
||||
}
|
||||
|
||||
err := s.SQLStore.WithTransactionalDbSession(ctx, func(session *db.Session) error {
|
||||
// Correlations created before the fix #72498 may have org_id = 0, but it's deprecated and will be removed in #72325
|
||||
found, err := session.Select("correlation.*").Join("", "data_source AS dss", "correlation.source_uid = dss.uid and (correlation.org_id = 0 or dss.org_id = correlation.org_id) and dss.org_id = ?", cmd.OrgId).Join("LEFT OUTER", "data_source AS dst", "correlation.target_uid = dst.uid and dst.org_id = ?", cmd.OrgId).Where("correlation.uid = ?", correlation.UID).And("correlation.source_uid = ?", correlation.SourceUID).And(VALID_TYPE_FILTER).Get(&correlation)
|
||||
sql := session.Select("correlation.*, dss.type as source_type, dst.type as target_type").
|
||||
Join("", "data_source AS dss", "correlation.source_uid = dss.uid and (correlation.org_id = 0 or dss.org_id = correlation.org_id) and dss.org_id = ?", cmd.OrgId).
|
||||
Join("LEFT OUTER", "data_source AS dst", "correlation.target_uid = dst.uid and dst.org_id = ?", cmd.OrgId).
|
||||
Where("correlation.uid = ?", correlation.UID).
|
||||
And("correlation.org_id = ?", correlation.OrgID).
|
||||
And(VALID_TYPE_FILTER)
|
||||
if correlation.SourceUID != "" {
|
||||
sql = sql.And("correlation.source_uid = ?", correlation.SourceUID)
|
||||
}
|
||||
found, err := sql.Get(&correlation)
|
||||
if !found {
|
||||
return ErrCorrelationNotFound
|
||||
}
|
||||
@@ -264,7 +279,9 @@ func (s CorrelationsService) getCorrelations(ctx context.Context, cmd GetCorrela
|
||||
offset := cmd.Limit * (cmd.Page - 1)
|
||||
|
||||
// Correlations created before the fix #72498 may have org_id = 0, but it's deprecated and will be removed in #72325
|
||||
q := session.Select("correlation.*").Join("", "data_source AS dss", "correlation.source_uid = dss.uid and (correlation.org_id = 0 or dss.org_id = correlation.org_id) and dss.org_id = ? ", cmd.OrgId).Join("LEFT OUTER", "data_source AS dst", "correlation.target_uid = dst.uid and dst.org_id = ?", cmd.OrgId)
|
||||
q := session.Select("correlation.*, dss.type as source_type, dst.type as target_type").
|
||||
Join("", "data_source AS dss", "correlation.source_uid = dss.uid and (correlation.org_id = 0 or dss.org_id = correlation.org_id) and dss.org_id = ? ", cmd.OrgId).
|
||||
Join("LEFT OUTER", "data_source AS dst", "correlation.target_uid = dst.uid and dst.org_id = ?", cmd.OrgId)
|
||||
|
||||
if len(cmd.SourceUIDs) > 0 {
|
||||
q.In("dss.uid", cmd.SourceUIDs)
|
||||
@@ -331,7 +348,7 @@ func (s CorrelationsService) createOrUpdateCorrelation(ctx context.Context, cmd
|
||||
|
||||
found := false
|
||||
err := s.SQLStore.WithDbSession(ctx, func(session *db.Session) error {
|
||||
has, err := session.Get(&correlation)
|
||||
has, err := session.Omit("source_type", "target_type").Get(&correlation)
|
||||
found = has
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -110,13 +110,15 @@ type Correlation struct {
|
||||
UID string `json:"uid" xorm:"pk 'uid'"`
|
||||
// UID of the data source the correlation originates from
|
||||
// example: d0oxYRg4z
|
||||
SourceUID string `json:"sourceUID" xorm:"pk 'source_uid'"`
|
||||
SourceUID string `json:"sourceUID" xorm:"pk 'source_uid'"`
|
||||
SourceType *string `json:"-" xorm:"source_type"`
|
||||
// OrgID of the data source the correlation originates from
|
||||
// Example: 1
|
||||
OrgID int64 `json:"orgId" xorm:"pk 'org_id'"`
|
||||
// UID of the data source the correlation points to
|
||||
// example: PE1C5CBDA0504A6A3
|
||||
TargetUID *string `json:"targetUID" xorm:"target_uid"`
|
||||
TargetUID *string `json:"targetUID" xorm:"target_uid"`
|
||||
TargetType *string `json:"-" xorm:"target_type"`
|
||||
// Label identifying the correlation
|
||||
// example: My Label
|
||||
Label string `json:"label" xorm:"label"`
|
||||
|
||||
Reference in New Issue
Block a user