mirror of
https://github.com/grafana/grafana.git
synced 2024-11-27 03:11:01 -06:00
8e6205c107
* move guts from cli to server * renaming + refactoring * add pluginsDir arg * arg fixes * add support for repo URL override * add funcs to interface * use pluginID consistently * swap args * pass mandatory grafanaVersion field * introduce logger interface * create central logger for CLI * add infra log wrapper * re-add log initer step * remove unused logger * add checks for uninstalling * improve debug blue * make sure to close file * fix linter issues * remove space * improve newline usage * refactor packaging * improve logger API * fix interface func names * close file and reformat zipslip catch * handle G305 linter warning * add helpful debug log
121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
package services
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
|
|
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
|
)
|
|
|
|
var (
|
|
IoHelper models.IoUtil = IoUtilImp{}
|
|
HttpClient http.Client
|
|
HttpClientNoTimeout http.Client
|
|
GrafanaVersion string
|
|
ErrNotFoundError = errors.New("404 not found error")
|
|
Logger *logger.CLILogger
|
|
)
|
|
|
|
type BadRequestError struct {
|
|
Message string
|
|
Status string
|
|
}
|
|
|
|
func (e *BadRequestError) Error() string {
|
|
if len(e.Message) > 0 {
|
|
return fmt.Sprintf("%s: %s", e.Status, e.Message)
|
|
}
|
|
return e.Status
|
|
}
|
|
|
|
func Init(version string, skipTLSVerify bool, debugMode bool) {
|
|
GrafanaVersion = version
|
|
|
|
HttpClient = makeHttpClient(skipTLSVerify, 10*time.Second)
|
|
HttpClientNoTimeout = makeHttpClient(skipTLSVerify, 0)
|
|
Logger = logger.New(debugMode)
|
|
}
|
|
|
|
func makeHttpClient(skipTLSVerify bool, timeout time.Duration) http.Client {
|
|
tr := &http.Transport{
|
|
Proxy: http.ProxyFromEnvironment,
|
|
DialContext: (&net.Dialer{
|
|
Timeout: 30 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
}).DialContext,
|
|
MaxIdleConns: 100,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: skipTLSVerify,
|
|
},
|
|
}
|
|
|
|
return http.Client{
|
|
Timeout: timeout,
|
|
Transport: tr,
|
|
}
|
|
}
|
|
|
|
func ReadPlugin(pluginDir, pluginName string) (models.InstalledPlugin, error) {
|
|
distPluginDataPath := filepath.Join(pluginDir, pluginName, "dist", "plugin.json")
|
|
|
|
data, err := IoHelper.ReadFile(distPluginDataPath)
|
|
if err != nil {
|
|
pluginDataPath := filepath.Join(pluginDir, pluginName, "plugin.json")
|
|
data, err = IoHelper.ReadFile(pluginDataPath)
|
|
if err != nil {
|
|
return models.InstalledPlugin{}, errors.New("Could not find dist/plugin.json or plugin.json on " + pluginName + " in " + pluginDir)
|
|
}
|
|
}
|
|
|
|
res := models.InstalledPlugin{}
|
|
if err := json.Unmarshal(data, &res); err != nil {
|
|
return res, err
|
|
}
|
|
|
|
if res.Info.Version == "" {
|
|
res.Info.Version = "0.0.0"
|
|
}
|
|
|
|
if res.ID == "" {
|
|
return models.InstalledPlugin{}, errors.New("could not find plugin " + pluginName + " in " + pluginDir)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func GetLocalPlugins(pluginDir string) []models.InstalledPlugin {
|
|
result := make([]models.InstalledPlugin, 0)
|
|
files, _ := IoHelper.ReadDir(pluginDir)
|
|
for _, f := range files {
|
|
res, err := ReadPlugin(pluginDir, f.Name())
|
|
if err == nil {
|
|
result = append(result, res)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func RemoveInstalledPlugin(pluginPath, pluginName string) error {
|
|
logger.Infof("Removing plugin: %v\n", pluginName)
|
|
pluginDir := filepath.Join(pluginPath, pluginName)
|
|
|
|
_, err := IoHelper.Stat(pluginDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logger.Debugf("Removing directory %v\n", pluginDir)
|
|
return IoHelper.RemoveAll(pluginDir)
|
|
}
|