| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package plugins
- import (
- "encoding/json"
- "fmt"
- "regexp"
- "github.com/grafana/grafana/pkg/bus"
- "github.com/grafana/grafana/pkg/components/simplejson"
- m "github.com/grafana/grafana/pkg/models"
- "github.com/grafana/grafana/pkg/services/dashboards"
- )
- type ImportDashboardCommand struct {
- Dashboard *simplejson.Json
- Path string
- Inputs []ImportDashboardInput
- Overwrite bool
- OrgId int64
- User *m.SignedInUser
- PluginId string
- Result *PluginDashboardInfoDTO
- }
- type ImportDashboardInput struct {
- Type string `json:"type"`
- PluginId string `json:"pluginId"`
- Name string `json:"name"`
- Value string `json:"value"`
- }
- type DashboardInputMissingError struct {
- VariableName string
- }
- func (e DashboardInputMissingError) Error() string {
- return fmt.Sprintf("Dashboard input variable: %v missing from import command", e.VariableName)
- }
- func init() {
- bus.AddHandler("plugins", ImportDashboard)
- }
- func ImportDashboard(cmd *ImportDashboardCommand) error {
- var dashboard *m.Dashboard
- var err error
- if cmd.PluginId != "" {
- if dashboard, err = loadPluginDashboard(cmd.PluginId, cmd.Path); err != nil {
- return err
- }
- } else {
- dashboard = m.NewDashboardFromJson(cmd.Dashboard)
- }
- evaluator := &DashTemplateEvaluator{
- template: dashboard.Data,
- inputs: cmd.Inputs,
- }
- generatedDash, err := evaluator.Eval()
- if err != nil {
- return err
- }
- saveCmd := m.SaveDashboardCommand{
- Dashboard: generatedDash,
- OrgId: cmd.OrgId,
- UserId: cmd.User.UserId,
- Overwrite: cmd.Overwrite,
- PluginId: cmd.PluginId,
- FolderId: dashboard.FolderId,
- }
- dto := &dashboards.SaveDashboardDTO{
- OrgId: cmd.OrgId,
- Dashboard: saveCmd.GetDashboardModel(),
- Overwrite: saveCmd.Overwrite,
- User: cmd.User,
- }
- savedDash, err := dashboards.NewService().ImportDashboard(dto)
- if err != nil {
- return err
- }
- cmd.Result = &PluginDashboardInfoDTO{
- PluginId: cmd.PluginId,
- Title: savedDash.Title,
- Path: cmd.Path,
- Revision: savedDash.Data.Get("revision").MustInt64(1),
- ImportedUri: "db/" + savedDash.Slug,
- ImportedUrl: savedDash.GetUrl(),
- ImportedRevision: dashboard.Data.Get("revision").MustInt64(1),
- Imported: true,
- }
- return nil
- }
- type DashTemplateEvaluator struct {
- template *simplejson.Json
- inputs []ImportDashboardInput
- variables map[string]string
- result *simplejson.Json
- varRegex *regexp.Regexp
- }
- func (this *DashTemplateEvaluator) findInput(varName string, varType string) *ImportDashboardInput {
- for _, input := range this.inputs {
- if varType == input.Type && (input.Name == varName || input.Name == "*") {
- return &input
- }
- }
- return nil
- }
- func (this *DashTemplateEvaluator) Eval() (*simplejson.Json, error) {
- this.result = simplejson.New()
- this.variables = make(map[string]string)
- this.varRegex, _ = regexp.Compile(`(\$\{.+\})`)
- // check that we have all inputs we need
- for _, inputDef := range this.template.Get("__inputs").MustArray() {
- inputDefJson := simplejson.NewFromAny(inputDef)
- inputName := inputDefJson.Get("name").MustString()
- inputType := inputDefJson.Get("type").MustString()
- input := this.findInput(inputName, inputType)
- if input == nil {
- return nil, &DashboardInputMissingError{VariableName: inputName}
- }
- this.variables["${"+inputName+"}"] = input.Value
- }
- return simplejson.NewFromAny(this.evalObject(this.template)), nil
- }
- func (this *DashTemplateEvaluator) evalValue(source *simplejson.Json) interface{} {
- sourceValue := source.Interface()
- switch v := sourceValue.(type) {
- case string:
- interpolated := this.varRegex.ReplaceAllStringFunc(v, func(match string) string {
- if replacement, exists := this.variables[match]; exists {
- return replacement
- } else {
- return match
- }
- })
- return interpolated
- case bool:
- return v
- case json.Number:
- return v
- case map[string]interface{}:
- return this.evalObject(source)
- case []interface{}:
- array := make([]interface{}, 0)
- for _, item := range v {
- array = append(array, this.evalValue(simplejson.NewFromAny(item)))
- }
- return array
- }
- return nil
- }
- func (this *DashTemplateEvaluator) evalObject(source *simplejson.Json) interface{} {
- result := make(map[string]interface{})
- for key, value := range source.MustMap() {
- if key == "__inputs" {
- continue
- }
- result[key] = this.evalValue(simplejson.NewFromAny(value))
- }
- return result
- }
|