github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/service/plugin.go (about)

     1  package service
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"net/http"
     7  	"path/filepath"
     8  
     9  	"github.com/evergreen-ci/evergreen/model/user"
    10  	"github.com/evergreen-ci/evergreen/plugin"
    11  )
    12  
    13  // pluginHTML the given set of template files and executes the template named entryPoint against
    14  // the context data, writing the result to out. Returns error if the template could not be
    15  // loaded or if executing the template failed.
    16  func (uis *UIServer) pluginHTML(out io.Writer, data interface{}, entryPoint, pluginName, pluginFile string, files ...string) error {
    17  
    18  	// check if the template is cached and execute cached template if so.
    19  	if uis.Settings.Ui.CacheTemplates {
    20  		if templ, ok := uis.PluginTemplates[pluginName]; ok {
    21  			return templ.ExecuteTemplate(out, entryPoint, data)
    22  		}
    23  	}
    24  
    25  	t, err := uis.GetHTMLTemplate(files...)
    26  	if err != nil {
    27  		return err
    28  	}
    29  	newTemplate, err := t.Clone()
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	newTemplate, err = newTemplate.ParseFiles(pluginFile)
    35  	if err != nil {
    36  		return err
    37  	}
    38  
    39  	// cache the template if necessary
    40  	if uis.Settings.Ui.CacheTemplates {
    41  		uis.PluginTemplates[pluginName] = newTemplate
    42  	}
    43  	err = newTemplate.ExecuteTemplate(out, entryPoint, data)
    44  	return err
    45  }
    46  
    47  // PluginWriteHTML calls HTML() on its args and writes the output to the response with the given status.
    48  // If the template can't be loaded or executed, the status is set to 500 and error details
    49  // are written to the response body.
    50  func (uis *UIServer) PluginWriteHTML(w http.ResponseWriter, status int, data interface{}, entryPoint, pluginName, pluginFile string, files ...string) {
    51  	out := &bytes.Buffer{}
    52  	err := uis.pluginHTML(out, data, entryPoint, pluginName, pluginFile, files...)
    53  	if err != nil {
    54  		http.Error(w, err.Error(), http.StatusInternalServerError)
    55  		return
    56  	}
    57  
    58  	w.Header().Set("Content-Type", "text/html; charset=UTF-8")
    59  	w.WriteHeader(status)
    60  	_, err = w.Write(out.Bytes())
    61  	if err != nil {
    62  		http.Error(w, err.Error(), http.StatusInternalServerError)
    63  	}
    64  }
    65  
    66  // GetPluginHandler returns a handler function given the template route and data to go to that page.
    67  func (uis *UIServer) GetPluginHandler(uiPage *plugin.UIPage, pluginName string) func(http.ResponseWriter, *http.Request) {
    68  	return func(w http.ResponseWriter, r *http.Request) {
    69  		projCtx := MustHaveProjectContext(r)
    70  		u := GetUser(r)
    71  		pluginCtx := plugin.UIContext{
    72  			Settings:   uis.Settings,
    73  			User:       u,
    74  			Task:       projCtx.Task,
    75  			Build:      projCtx.Build,
    76  			Version:    projCtx.Version,
    77  			Patch:      projCtx.Patch,
    78  			Project:    projCtx.Project,
    79  			ProjectRef: projCtx.ProjectRef,
    80  			Request:    r,
    81  		}
    82  		pluginData, err := uiPage.DataFunc(pluginCtx)
    83  		if err != nil {
    84  			http.Error(w, err.Error(), http.StatusInternalServerError)
    85  			return
    86  		}
    87  		data := struct {
    88  			Data        interface{}
    89  			User        *user.DBUser
    90  			ProjectData projectContext
    91  		}{pluginData, u, projCtx}
    92  
    93  		pluginTemplatePath := filepath.Join(plugin.TemplateRoot(pluginName), uiPage.TemplatePath)
    94  		uis.PluginWriteHTML(w, http.StatusOK, data, "base", pluginName, pluginTemplatePath, "base_angular.html", "menu.html")
    95  	}
    96  }