mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			191 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
| 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
 | |
| 	FolderId  int64
 | |
| 
 | |
| 	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:  cmd.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),
 | |
| 		FolderId:         savedDash.FolderId,
 | |
| 		ImportedUri:      "db/" + savedDash.Slug,
 | |
| 		ImportedUrl:      savedDash.GetUrl(),
 | |
| 		ImportedRevision: dashboard.Data.Get("revision").MustInt64(1),
 | |
| 		Imported:         true,
 | |
| 		DashboardId:      savedDash.Id,
 | |
| 		Slug:             savedDash.Slug,
 | |
| 	}
 | |
| 
 | |
| 	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 {
 | |
| 			replacement, exists := this.variables[match]
 | |
| 			if exists {
 | |
| 				return replacement
 | |
| 			}
 | |
| 			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
 | |
| }
 |