[Fix]: Using exported dashboards as input to dashboard provisioning #2 (#4726)

* fix(be,fe): upsert dashboard on provision, export with uuid from frontend

* chore(fe): formatting in dashboard description

* fix: miss out while merging

---------

Co-authored-by: Håvard <haavard.markhus@inmeta.no>
Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
Co-authored-by: Haavasma <61970295+Haavasma@users.noreply.github.com>
This commit is contained in:
Tan Wei Been 2024-03-26 19:39:59 +08:00 committed by GitHub
parent 4c91dbcff0
commit 2b3d1c8ee5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 17 deletions

View File

@ -23,7 +23,12 @@ function DashboardDescription(): JSX.Element {
handleDashboardLockToggle,
} = useDashboard();
const selectedData = selectedDashboard?.data || ({} as DashboardData);
const selectedData = selectedDashboard
? {
...selectedDashboard.data,
uuid: selectedDashboard.uuid,
}
: ({} as DashboardData);
const { title = '', tags, description } = selectedData || {};

View File

@ -55,6 +55,7 @@ export interface Dashboard {
}
export interface DashboardData {
uuid?: string;
description?: string;
tags?: string[];
name?: string;

View File

@ -25,12 +25,14 @@ import (
var db *sqlx.DB
// User for mapping job,instance from grafana
var instanceEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.instance}}\\\"")
var nodeEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.node}}\\\"")
var jobEQRE = regexp.MustCompile("job(?s)=(?s)\\\"{{.job}}\\\"")
var instanceRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.instance}}\\\"")
var nodeRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.node}}\\\"")
var jobRERE = regexp.MustCompile("job(?s)=~(?s)\\\"{{.job}}\\\"")
var (
instanceEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.instance}}\\\"")
nodeEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.node}}\\\"")
jobEQRE = regexp.MustCompile("job(?s)=(?s)\\\"{{.job}}\\\"")
instanceRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.instance}}\\\"")
nodeRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.node}}\\\"")
jobRERE = regexp.MustCompile("job(?s)=~(?s)\\\"{{.job}}\\\"")
)
// InitDB sets up setting up the connection pool global variable.
func InitDB(dataSourceName string) (*sqlx.DB, error) {
@ -188,6 +190,9 @@ func CreateDashboard(ctx context.Context, data map[string]interface{}, fm interf
dash.UpdateBy = &userEmail
dash.UpdateSlug()
dash.Uuid = uuid.New().String()
if data["uuid"] != nil {
dash.Uuid = data["uuid"].(string)
}
mapData, err := json.Marshal(dash.Data)
if err != nil {
@ -211,7 +216,6 @@ func CreateDashboard(ctx context.Context, data map[string]interface{}, fm interf
return nil, &model.ApiError{Typ: model.ErrorExec, Err: err}
}
lastInsertId, err := result.LastInsertId()
if err != nil {
return nil, &model.ApiError{Typ: model.ErrorExec, Err: err}
}
@ -255,7 +259,6 @@ func DeleteDashboard(ctx context.Context, uuid string, fm interfaces.FeatureLook
query := `DELETE FROM dashboards WHERE uuid=?`
result, err := db.Exec(query, uuid)
if err != nil {
return &model.ApiError{Typ: model.ErrorExec, Err: err}
}
@ -419,7 +422,6 @@ func (d *Dashboard) UpdateSlug() {
}
func IsPostDataSane(data *map[string]interface{}) error {
val, ok := (*data)["title"]
if !ok || val == nil {
return fmt.Errorf("title not found in post data")

View File

@ -10,6 +10,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/interfaces"
"go.signoz.io/signoz/pkg/query-service/model"
)
func readCurrentDir(dir string, fm interfaces.FeatureLookup) error {
@ -43,22 +44,36 @@ func readCurrentDir(dir string, fm interfaces.FeatureLookup) error {
continue
}
_, apiErr := GetDashboard(context.Background(), data["uuid"].(string))
if apiErr == nil {
zap.S().Infof("Creating Dashboards: Error in file: %s\t%s", filename, "Dashboard already present in database")
id := data["uuid"]
if id == nil {
_, apiErr := CreateDashboard(context.Background(), data, fm)
if apiErr != nil {
zap.S().Errorf("Creating Dashboards: Error in file: %s\t%s", filename, apiErr.Err)
}
continue
}
_, apiErr = CreateDashboard(context.Background(), data, fm)
apiErr := upsertDashboard(id.(string), data, filename, fm)
if apiErr != nil {
zap.S().Errorf("Creating Dashboards: Error in file: %s\t%s", filename, apiErr.Err)
continue
zap.S().Errorf("Creating Dashboards: Error upserting dashboard: %s\t%s", filename, apiErr.Err)
}
}
return nil
}
func upsertDashboard(uuid string, data map[string]interface{}, filename string, fm interfaces.FeatureLookup) *model.ApiError {
_, apiErr := GetDashboard(context.Background(), uuid)
if apiErr == nil {
zap.S().Infof("Creating Dashboards: Already exists: %s\t%s", filename, "Dashboard already present in database, Updating dashboard")
_, apiErr := UpdateDashboard(context.Background(), uuid, data, fm)
return apiErr
}
zap.S().Infof("Creating Dashboards: UUID not found: %s\t%s", filename, "Dashboard not present in database, Creating dashboard")
_, apiErr = CreateDashboard(context.Background(), data, fm)
return apiErr
}
func LoadDashboardFiles(fm interfaces.FeatureLookup) error {
dashboardsPath := constants.GetOrDefaultEnv("DASHBOARDS_PATH", "./config/dashboards")
return readCurrentDir(dashboardsPath, fm)