Merge remote-tracking branch 'origin/master' into style-changes-bulletfactory
This commit is contained in:
@@ -61,7 +61,7 @@ func init() {
|
||||
"AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
|
||||
"AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
|
||||
"AWS/RDS": {"BinLogDiskUsage", "CPUUtilization", "CPUCreditUsage", "CPUCreditBalance", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
|
||||
"AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy"},
|
||||
"AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy", "ConnectionTime", "SSLHandshakeTime", "TimeToFirstByte"},
|
||||
"AWS/SNS": {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
|
||||
"AWS/SQS": {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
|
||||
"AWS/S3": {"BucketSizeBytes", "NumberOfObjects"},
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
@@ -16,7 +15,7 @@ func populateDashboardsById(dashboardByIds []int64) ([]m.PlaylistDashboardDto, e
|
||||
if len(dashboardByIds) > 0 {
|
||||
dashboardQuery := m.GetDashboardsQuery{DashboardIds: dashboardByIds}
|
||||
if err := bus.Dispatch(&dashboardQuery); err != nil {
|
||||
return result, errors.New("Playlist not found") //TODO: dont swallow error
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, item := range *dashboardQuery.Result {
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ func SignUpStep2(c *middleware.Context, form dtos.SignUpStep2Form) Response {
|
||||
return ApiError(500, "Failed to query database for invites", err)
|
||||
}
|
||||
|
||||
apiResponse := util.DynMap{"message": "User sign up completed succesfully", "code": "redirect-to-landing-page"}
|
||||
apiResponse := util.DynMap{"message": "User sign up completed successfully", "code": "redirect-to-landing-page"}
|
||||
for _, invite := range invitesQuery.Result {
|
||||
if ok, rsp := applyUserInvite(user, invite, false); !ok {
|
||||
return rsp
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
type CommandLine interface {
|
||||
ShowHelp()
|
||||
ShowVersion()
|
||||
Application() *cli.App
|
||||
Args() cli.Args
|
||||
Bool(name string) bool
|
||||
Int(name string) int
|
||||
String(name string) string
|
||||
StringSlice(name string) []string
|
||||
GlobalString(name string) string
|
||||
FlagNames() (names []string)
|
||||
Generic(name string) interface{}
|
||||
}
|
||||
|
||||
type contextCommandLine struct {
|
||||
*cli.Context
|
||||
}
|
||||
|
||||
func (c *contextCommandLine) ShowHelp() {
|
||||
cli.ShowCommandHelp(c.Context, c.Command.Name)
|
||||
}
|
||||
|
||||
func (c *contextCommandLine) ShowVersion() {
|
||||
cli.ShowVersion(c.Context)
|
||||
}
|
||||
|
||||
func (c *contextCommandLine) Application() *cli.App {
|
||||
return c.App
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func runCommand(command func(commandLine CommandLine) error) func(context *cli.Context) {
|
||||
return func(context *cli.Context) {
|
||||
|
||||
cmd := &contextCommandLine{context}
|
||||
if err := command(cmd); err != nil {
|
||||
log.Errorf("%v\n\n", err)
|
||||
|
||||
cmd.ShowHelp()
|
||||
os.Exit(1)
|
||||
} else {
|
||||
log.Info("\nRestart grafana after installing plugins . <service grafana-server restart>\n\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var Commands = []cli.Command{
|
||||
{
|
||||
Name: "install",
|
||||
Usage: "install <plugin name>",
|
||||
Action: runCommand(installCommand),
|
||||
}, {
|
||||
Name: "list-remote",
|
||||
Usage: "list remote available plugins",
|
||||
Action: runCommand(listremoteCommand),
|
||||
}, {
|
||||
Name: "upgrade",
|
||||
Usage: "upgrade <plugin name>",
|
||||
Action: runCommand(upgradeCommand),
|
||||
}, {
|
||||
Name: "upgrade-all",
|
||||
Usage: "upgrades all your installed plugins",
|
||||
Action: runCommand(upgradeAllCommand),
|
||||
}, {
|
||||
Name: "ls",
|
||||
Usage: "list all installed plugins",
|
||||
Action: runCommand(lsCommand),
|
||||
}, {
|
||||
Name: "remove",
|
||||
Usage: "remove <plugin name>",
|
||||
Action: runCommand(removeCommand),
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package commandstest
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
type FakeFlagger struct {
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
type FakeCommandLine struct {
|
||||
LocalFlags, GlobalFlags *FakeFlagger
|
||||
HelpShown, VersionShown bool
|
||||
CliArgs []string
|
||||
}
|
||||
|
||||
func (ff FakeFlagger) String(key string) string {
|
||||
if value, ok := ff.Data[key]; ok {
|
||||
return value.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ff FakeFlagger) StringSlice(key string) []string {
|
||||
if value, ok := ff.Data[key]; ok {
|
||||
return value.([]string)
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (ff FakeFlagger) Int(key string) int {
|
||||
if value, ok := ff.Data[key]; ok {
|
||||
return value.(int)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ff FakeFlagger) Bool(key string) bool {
|
||||
if value, ok := ff.Data[key]; ok {
|
||||
return value.(bool)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) String(key string) string {
|
||||
return fcli.LocalFlags.String(key)
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) StringSlice(key string) []string {
|
||||
return fcli.LocalFlags.StringSlice(key)
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) Int(key string) int {
|
||||
return fcli.LocalFlags.Int(key)
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) Bool(key string) bool {
|
||||
if fcli.LocalFlags == nil {
|
||||
return false
|
||||
}
|
||||
return fcli.LocalFlags.Bool(key)
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) GlobalString(key string) string {
|
||||
return fcli.GlobalFlags.String(key)
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) Generic(name string) interface{} {
|
||||
return fcli.LocalFlags.Data[name]
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) FlagNames() []string {
|
||||
flagNames := []string{}
|
||||
for key := range fcli.LocalFlags.Data {
|
||||
flagNames = append(flagNames, key)
|
||||
}
|
||||
|
||||
return flagNames
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) ShowHelp() {
|
||||
fcli.HelpShown = true
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) Application() *cli.App {
|
||||
return cli.NewApp()
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) Args() cli.Args {
|
||||
return fcli.CliArgs
|
||||
}
|
||||
|
||||
func (fcli *FakeCommandLine) ShowVersion() {
|
||||
fcli.VersionShown = true
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package commandstest
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FakeIoUtil struct {
|
||||
FakeReadDir []os.FileInfo
|
||||
FakeIsDirectory bool
|
||||
}
|
||||
|
||||
func (util *FakeIoUtil) Stat(path string) (os.FileInfo, error) {
|
||||
return &FakeFileInfo{IsDirectory: util.FakeIsDirectory}, nil
|
||||
}
|
||||
|
||||
func (util *FakeIoUtil) RemoveAll(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (util *FakeIoUtil) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return util.FakeReadDir, nil
|
||||
}
|
||||
|
||||
func (i *FakeIoUtil) ReadFile(filename string) ([]byte, error) {
|
||||
return make([]byte, 0), nil
|
||||
}
|
||||
|
||||
type FakeFileInfo struct {
|
||||
IsDirectory bool
|
||||
}
|
||||
|
||||
func (ffi *FakeFileInfo) IsDir() bool {
|
||||
return ffi.IsDirectory
|
||||
}
|
||||
|
||||
func (ffi FakeFileInfo) Size() int64 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (ffi FakeFileInfo) Mode() os.FileMode {
|
||||
return 0777
|
||||
}
|
||||
|
||||
func (ffi FakeFileInfo) Name() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ffi FakeFileInfo) ModTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (ffi FakeFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func validateInput(c CommandLine, pluginFolder string) error {
|
||||
arg := c.Args().First()
|
||||
if arg == "" {
|
||||
return errors.New("please specify plugin to install")
|
||||
}
|
||||
|
||||
pluginDir := c.GlobalString("path")
|
||||
if pluginDir == "" {
|
||||
return errors.New("missing path flag")
|
||||
}
|
||||
|
||||
fileinfo, err := os.Stat(pluginDir)
|
||||
if err != nil && !fileinfo.IsDir() {
|
||||
return errors.New("path is not a directory")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func installCommand(c CommandLine) error {
|
||||
pluginFolder := c.GlobalString("path")
|
||||
if err := validateInput(c, pluginFolder); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pluginToInstall := c.Args().First()
|
||||
version := c.Args().Get(1)
|
||||
|
||||
log.Infof("version: %v\n", version)
|
||||
|
||||
return InstallPlugin(pluginToInstall, pluginFolder, version)
|
||||
}
|
||||
|
||||
func InstallPlugin(pluginName, pluginFolder, version string) error {
|
||||
plugin, err := s.GetPlugin(pluginName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, err := SelectVersion(plugin, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := v.Url
|
||||
commit := v.Commit
|
||||
|
||||
downloadURL := url + "/archive/" + commit + ".zip"
|
||||
|
||||
log.Infof("installing %v @ %v\n", plugin.Id, version)
|
||||
log.Infof("from url: %v\n", downloadURL)
|
||||
log.Infof("on commit: %v\n", commit)
|
||||
log.Infof("into: %v\n", pluginFolder)
|
||||
|
||||
err = downloadFile(plugin.Id, pluginFolder, downloadURL)
|
||||
if err == nil {
|
||||
log.Infof("Installed %v successfully ✔\n", plugin.Id)
|
||||
}
|
||||
|
||||
res, _ := s.ReadPlugin(pluginFolder, pluginName)
|
||||
|
||||
for _, v := range res.Dependency.Plugins {
|
||||
InstallPlugin(v.Id, pluginFolder, "")
|
||||
log.Infof("Installed Dependency: %v ✔\n", v.Id)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func SelectVersion(plugin m.Plugin, version string) (m.Version, error) {
|
||||
if version == "" {
|
||||
return plugin.Versions[0], nil
|
||||
}
|
||||
|
||||
for _, v := range plugin.Versions {
|
||||
if v.Version == version {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
return m.Version{}, errors.New("Could not find the version your looking for")
|
||||
}
|
||||
|
||||
func RemoveGitBuildFromname(pluginname, filename string) string {
|
||||
r := regexp.MustCompile("^[a-zA-Z0-9_.-]*/")
|
||||
return r.ReplaceAllString(filename, pluginname+"/")
|
||||
}
|
||||
|
||||
func downloadFile(pluginName, filepath, url string) (err error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := zip.NewReader(bytes.NewReader(body), resp.ContentLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, zf := range r.File {
|
||||
newfile := path.Join(filepath, RemoveGitBuildFromname(pluginName, zf.Name))
|
||||
|
||||
if zf.FileInfo().IsDir() {
|
||||
os.Mkdir(newfile, 0777)
|
||||
} else {
|
||||
dst, err := os.Create(newfile)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
src, err := zf.Open()
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
io.Copy(dst, src)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestFoldernameReplacement(t *testing.T) {
|
||||
Convey("path containing git commit path", t, func() {
|
||||
pluginName := "datasource-plugin-kairosdb"
|
||||
|
||||
paths := map[string]string{
|
||||
"datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/": "datasource-plugin-kairosdb/",
|
||||
"datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/README.md": "datasource-plugin-kairosdb/README.md",
|
||||
"datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/partials/": "datasource-plugin-kairosdb/partials/",
|
||||
"datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/partials/config.html": "datasource-plugin-kairosdb/partials/config.html",
|
||||
}
|
||||
|
||||
Convey("should be replaced with plugin name", func() {
|
||||
for k, v := range paths {
|
||||
So(RemoveGitBuildFromname(pluginName, k), ShouldEqual, v)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Convey("path containing git commit path", t, func() {
|
||||
pluginName := "app-example"
|
||||
paths := map[string]string{
|
||||
"app-plugin-example-3c28f65ac6fb7f1e234b0364b97081d836495439/": "app-example/",
|
||||
}
|
||||
|
||||
Convey("should be replaced with plugin name", func() {
|
||||
for k, v := range paths {
|
||||
So(RemoveGitBuildFromname(pluginName, k), ShouldEqual, v)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
)
|
||||
|
||||
func listremoteCommand(c CommandLine) error {
|
||||
plugin, err := s.ListAllPlugins()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, i := range plugin.Plugins {
|
||||
log.Infof("id: %v version:\n", i.Id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
)
|
||||
|
||||
var ls_getPlugins func(path string) []m.InstalledPlugin = s.GetLocalPlugins
|
||||
|
||||
var validateLsCommmand = func(pluginDir string) error {
|
||||
if pluginDir == "" {
|
||||
return errors.New("missing path flag")
|
||||
}
|
||||
|
||||
log.Info("plugindir: " + pluginDir + "\n")
|
||||
pluginDirInfo, err := s.IoHelper.Stat(pluginDir)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("missing path flag")
|
||||
}
|
||||
|
||||
if pluginDirInfo.IsDir() == false {
|
||||
return errors.New("plugin path is not a directory")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lsCommand(c CommandLine) error {
|
||||
pluginDir := c.GlobalString("path")
|
||||
if err := validateLsCommmand(pluginDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, plugin := range ls_getPlugins(pluginDir) {
|
||||
log.Infof("plugin: %s @ %s \n", plugin.Name, plugin.Info.Version)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/commands/commandstest"
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMissingPath(t *testing.T) {
|
||||
var org = validateLsCommmand
|
||||
|
||||
Convey("ls command", t, func() {
|
||||
validateLsCommmand = org
|
||||
|
||||
Convey("Missing path", func() {
|
||||
commandLine := &commandstest.FakeCommandLine{
|
||||
CliArgs: []string{"ls"},
|
||||
GlobalFlags: &commandstest.FakeFlagger{
|
||||
Data: map[string]interface{}{
|
||||
"path": "",
|
||||
},
|
||||
},
|
||||
}
|
||||
s.IoHelper = &commandstest.FakeIoUtil{}
|
||||
|
||||
Convey("should return error", func() {
|
||||
err := lsCommand(commandLine)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Path is not a directory", func() {
|
||||
commandLine := &commandstest.FakeCommandLine{
|
||||
CliArgs: []string{"ls"},
|
||||
GlobalFlags: &commandstest.FakeFlagger{
|
||||
Data: map[string]interface{}{
|
||||
"path": "/var/lib/grafana/plugins",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
s.IoHelper = &commandstest.FakeIoUtil{
|
||||
FakeIsDirectory: false,
|
||||
}
|
||||
|
||||
Convey("should return error", func() {
|
||||
err := lsCommand(commandLine)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("can override validateLsCommand", func() {
|
||||
commandLine := &commandstest.FakeCommandLine{
|
||||
CliArgs: []string{"ls"},
|
||||
GlobalFlags: &commandstest.FakeFlagger{
|
||||
Data: map[string]interface{}{
|
||||
"path": "/var/lib/grafana/plugins",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
validateLsCommmand = func(pluginDir string) error {
|
||||
return errors.New("dummie error")
|
||||
}
|
||||
|
||||
Convey("should return error", func() {
|
||||
err := lsCommand(commandLine)
|
||||
So(err.Error(), ShouldEqual, "dummie error")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Validate that validateLsCommand is reset", func() {
|
||||
commandLine := &commandstest.FakeCommandLine{
|
||||
CliArgs: []string{"ls"},
|
||||
GlobalFlags: &commandstest.FakeFlagger{
|
||||
Data: map[string]interface{}{
|
||||
"path": "/var/lib/grafana/plugins",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Convey("should return error", func() {
|
||||
err := lsCommand(commandLine)
|
||||
So(err.Error(), ShouldNotEqual, "dummie error")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
services "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
)
|
||||
|
||||
var getPluginss func(path string) []m.InstalledPlugin = services.GetLocalPlugins
|
||||
var removePlugin func(pluginPath, id string) error = services.RemoveInstalledPlugin
|
||||
|
||||
func removeCommand(c CommandLine) error {
|
||||
pluginPath := c.GlobalString("path")
|
||||
localPlugins := getPluginss(pluginPath)
|
||||
|
||||
log.Info("remove!\n")
|
||||
|
||||
plugin := c.Args().First()
|
||||
log.Info("plugin: " + plugin + "\n")
|
||||
if plugin == "" {
|
||||
return errors.New("Missing plugin parameter")
|
||||
}
|
||||
|
||||
log.Infof("plugins : \n%v\n", localPlugins)
|
||||
|
||||
for _, p := range localPlugins {
|
||||
if p.Id == c.Args().First() {
|
||||
log.Infof("removing plugin %s", p.Id)
|
||||
removePlugin(pluginPath, p.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
func ShouldUpgrade(installed string, remote m.Plugin) bool {
|
||||
installedVersion, err1 := version.NewVersion(installed)
|
||||
|
||||
if err1 != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, v := range remote.Versions {
|
||||
remoteVersion, err2 := version.NewVersion(v.Version)
|
||||
|
||||
if err2 == nil {
|
||||
if installedVersion.LessThan(remoteVersion) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func upgradeAllCommand(c CommandLine) error {
|
||||
pluginDir := c.GlobalString("path")
|
||||
|
||||
localPlugins := s.GetLocalPlugins(pluginDir)
|
||||
|
||||
remotePlugins, err := s.ListAllPlugins()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pluginsToUpgrade := make([]m.InstalledPlugin, 0)
|
||||
|
||||
for _, localPlugin := range localPlugins {
|
||||
for _, remotePlugin := range remotePlugins.Plugins {
|
||||
if localPlugin.Id == remotePlugin.Id {
|
||||
if ShouldUpgrade(localPlugin.Info.Version, remotePlugin) {
|
||||
pluginsToUpgrade = append(pluginsToUpgrade, localPlugin)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range pluginsToUpgrade {
|
||||
log.Infof("Upgrading %v \n", p.Id)
|
||||
|
||||
s.RemoveInstalledPlugin(pluginDir, p.Id)
|
||||
InstallPlugin(p.Id, pluginDir, "")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestVersionComparsion(t *testing.T) {
|
||||
Convey("Validate that version is outdated", t, func() {
|
||||
versions := []m.Version{
|
||||
{Version: "1.1.1"},
|
||||
{Version: "2.0.0"},
|
||||
}
|
||||
|
||||
shouldUpgrade := map[string]m.Plugin{
|
||||
"0.0.0": {Versions: versions},
|
||||
"1.0.0": {Versions: versions},
|
||||
}
|
||||
|
||||
Convey("should return error", func() {
|
||||
for k, v := range shouldUpgrade {
|
||||
So(ShouldUpgrade(k, v), ShouldBeTrue)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Validate that version is ok", t, func() {
|
||||
versions := []m.Version{
|
||||
{Version: "1.1.1"},
|
||||
{Version: "2.0.0"},
|
||||
}
|
||||
|
||||
shouldNotUpgrade := map[string]m.Plugin{
|
||||
"2.0.0": {Versions: versions},
|
||||
"6.0.0": {Versions: versions},
|
||||
}
|
||||
|
||||
Convey("should return error", func() {
|
||||
for k, v := range shouldNotUpgrade {
|
||||
So(ShouldUpgrade(k, v), ShouldBeFalse)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
|
||||
)
|
||||
|
||||
func upgradeCommand(c CommandLine) error {
|
||||
pluginDir := c.GlobalString("path")
|
||||
pluginName := c.Args().First()
|
||||
|
||||
localPlugin, err := s.ReadPlugin(pluginDir, pluginName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
remotePlugins, err2 := s.ListAllPlugins()
|
||||
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
for _, v := range remotePlugins.Plugins {
|
||||
if localPlugin.Id == v.Id {
|
||||
if ShouldUpgrade(localPlugin.Info.Version, v) {
|
||||
s.RemoveInstalledPlugin(pluginDir, pluginName)
|
||||
return InstallPlugin(localPlugin.Id, pluginDir, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
debugmode = false
|
||||
)
|
||||
|
||||
func Debug(args ...interface{}) {
|
||||
if debugmode {
|
||||
fmt.Print(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func Debugf(fmtString string, args ...interface{}) {
|
||||
if debugmode {
|
||||
fmt.Printf(fmtString, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func Error(args ...interface{}) {
|
||||
fmt.Print(args...)
|
||||
}
|
||||
|
||||
func Errorf(fmtString string, args ...interface{}) {
|
||||
fmt.Printf(fmtString, args...)
|
||||
}
|
||||
|
||||
func Info(args ...interface{}) {
|
||||
fmt.Print(args...)
|
||||
}
|
||||
|
||||
func Infof(fmtString string, args ...interface{}) {
|
||||
fmt.Printf(fmtString, args...)
|
||||
}
|
||||
|
||||
func Warn(args ...interface{}) {
|
||||
fmt.Print(args...)
|
||||
}
|
||||
|
||||
func Warnf(fmtString string, args ...interface{}) {
|
||||
fmt.Printf(fmtString, args...)
|
||||
}
|
||||
|
||||
func SetDebug(value bool) {
|
||||
debugmode = value
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/commands"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var version = "master"
|
||||
|
||||
func getGrafanaPluginPath() string {
|
||||
//TODO: try to get path from os:env GF_PLUGIN_FOLDER
|
||||
|
||||
os := runtime.GOOS
|
||||
if os == "windows" {
|
||||
return "C:\\opt\\grafana\\plugins"
|
||||
} else {
|
||||
return "/var/lib/grafana/plugins"
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
SetupLogging()
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "Grafana cli"
|
||||
app.Author = "raintank"
|
||||
app.Email = "https://github.com/grafana/grafana"
|
||||
app.Version = version
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "path",
|
||||
Usage: "path to the grafana installation",
|
||||
Value: getGrafanaPluginPath(),
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug, d",
|
||||
Usage: "enable debug logging",
|
||||
},
|
||||
}
|
||||
|
||||
app.Commands = commands.Commands
|
||||
app.CommandNotFound = cmdNotFound
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Errorf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func SetupLogging() {
|
||||
for _, f := range os.Args {
|
||||
if f == "-D" || f == "--debug" || f == "-debug" {
|
||||
log.SetDebug(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cmdNotFound(c *cli.Context, command string) {
|
||||
fmt.Printf(
|
||||
"%s: '%s' is not a %s command. See '%s --help'.\n",
|
||||
c.App.Name,
|
||||
command,
|
||||
c.App.Name,
|
||||
os.Args[0],
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type InstalledPlugin struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
|
||||
Info PluginInfo `json:"info"`
|
||||
Dependency Dependency `json:"dependencies"`
|
||||
}
|
||||
|
||||
type Dependency struct {
|
||||
GrafanaVersion string `json:"grafanaVersion"`
|
||||
Plugins []Plugin `json:"plugins"`
|
||||
}
|
||||
|
||||
type PluginInfo struct {
|
||||
Version string `json:"version"`
|
||||
Updated string `json:"updated"`
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
Id string `json:"id"`
|
||||
Category string `json:"category"`
|
||||
Versions []Version `json:"versions"`
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
Commit string `json:"commit"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type PluginRepo struct {
|
||||
Plugins []Plugin `json:"plugins"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type IoUtil interface {
|
||||
Stat(path string) (os.FileInfo, error)
|
||||
RemoveAll(path string) error
|
||||
ReadDir(path string) ([]os.FileInfo, error)
|
||||
ReadFile(filename string) ([]byte, error)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
type IoUtilImp struct {
|
||||
}
|
||||
|
||||
func (i IoUtilImp) Stat(path string) (os.FileInfo, error) {
|
||||
return os.Stat(path)
|
||||
}
|
||||
|
||||
func (i IoUtilImp) RemoveAll(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
func (i IoUtilImp) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return ioutil.ReadDir(path)
|
||||
}
|
||||
|
||||
func (i IoUtilImp) ReadFile(filename string) ([]byte, error) {
|
||||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/franela/goreq"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
|
||||
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
|
||||
"path"
|
||||
)
|
||||
|
||||
var IoHelper m.IoUtil = IoUtilImp{}
|
||||
|
||||
func ListAllPlugins() (m.PluginRepo, error) {
|
||||
res, _ := goreq.Request{Uri: "https://raw.githubusercontent.com/grafana/grafana-plugin-repository/master/repo.json"}.Do()
|
||||
|
||||
var resp m.PluginRepo
|
||||
err := res.Body.FromJsonTo(&resp)
|
||||
if err != nil {
|
||||
return m.PluginRepo{}, errors.New("Could not load plugin data")
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) {
|
||||
pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json")
|
||||
pluginData, _ := IoHelper.ReadFile(pluginDataPath)
|
||||
|
||||
res := m.InstalledPlugin{}
|
||||
json.Unmarshal(pluginData, &res)
|
||||
|
||||
if res.Info.Version == "" {
|
||||
res.Info.Version = "0.0.0"
|
||||
}
|
||||
|
||||
if res.Id == "" {
|
||||
return m.InstalledPlugin{}, errors.New("could not read find plugin " + pluginName)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func GetLocalPlugins(pluginDir string) []m.InstalledPlugin {
|
||||
result := make([]m.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, id string) error {
|
||||
log.Infof("Removing plugin: %v\n", id)
|
||||
return IoHelper.RemoveAll(path.Join(pluginPath, id))
|
||||
}
|
||||
|
||||
func GetPlugin(id string) (m.Plugin, error) {
|
||||
resp, err := ListAllPlugins()
|
||||
if err != nil {
|
||||
}
|
||||
|
||||
for _, i := range resp.Plugins {
|
||||
if i.Id == id {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
return m.Plugin{}, errors.New("could not find plugin named \"" + id + "\"")
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/login"
|
||||
"github.com/grafana/grafana/pkg/metrics"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/eventpublisher"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/social"
|
||||
)
|
||||
|
||||
var version = "master"
|
||||
var commit = "NA"
|
||||
var buildstamp string
|
||||
var build_date string
|
||||
|
||||
var configFile = flag.String("config", "", "path to config file")
|
||||
var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory")
|
||||
var pidFile = flag.String("pidfile", "", "path to pid file")
|
||||
var exitChan = make(chan int)
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
v := flag.Bool("v", false, "prints current version and exits")
|
||||
flag.Parse()
|
||||
if *v {
|
||||
fmt.Printf("Version %s (commit: %s)\n", version, commit)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
buildstampInt64, _ := strconv.ParseInt(buildstamp, 10, 64)
|
||||
|
||||
setting.BuildVersion = version
|
||||
setting.BuildCommit = commit
|
||||
setting.BuildStamp = buildstampInt64
|
||||
|
||||
go listenToSystemSignels()
|
||||
|
||||
flag.Parse()
|
||||
writePIDFile()
|
||||
initRuntime()
|
||||
|
||||
search.Init()
|
||||
login.Init()
|
||||
social.NewOAuthService()
|
||||
eventpublisher.Init()
|
||||
plugins.Init()
|
||||
|
||||
if err := notifications.Init(); err != nil {
|
||||
log.Fatal(3, "Notification service failed to initialize", err)
|
||||
}
|
||||
|
||||
if setting.ReportingEnabled {
|
||||
go metrics.StartUsageReportLoop()
|
||||
}
|
||||
|
||||
StartServer()
|
||||
exitChan <- 0
|
||||
}
|
||||
|
||||
func initRuntime() {
|
||||
err := setting.NewConfigContext(&setting.CommandLineArgs{
|
||||
Config: *configFile,
|
||||
HomePath: *homePath,
|
||||
Args: flag.Args(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(3, err.Error())
|
||||
}
|
||||
|
||||
log.Info("Starting Grafana")
|
||||
log.Info("Version: %v, Commit: %v, Build date: %v", setting.BuildVersion, setting.BuildCommit, time.Unix(setting.BuildStamp, 0))
|
||||
setting.LogConfigurationInfo()
|
||||
|
||||
sqlstore.NewEngine()
|
||||
sqlstore.EnsureAdminUser()
|
||||
}
|
||||
|
||||
func writePIDFile() {
|
||||
if *pidFile == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the required directory structure exists.
|
||||
err := os.MkdirAll(filepath.Dir(*pidFile), 0700)
|
||||
if err != nil {
|
||||
log.Fatal(3, "Failed to verify pid directory", err)
|
||||
}
|
||||
|
||||
// Retrieve the PID and write it.
|
||||
pid := strconv.Itoa(os.Getpid())
|
||||
if err := ioutil.WriteFile(*pidFile, []byte(pid), 0644); err != nil {
|
||||
log.Fatal(3, "Failed to write pidfile", err)
|
||||
}
|
||||
}
|
||||
|
||||
func listenToSystemSignels() {
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
code := 0
|
||||
|
||||
signal.Notify(signalChan, os.Interrupt)
|
||||
signal.Notify(signalChan, os.Kill)
|
||||
signal.Notify(signalChan, syscall.SIGTERM)
|
||||
|
||||
select {
|
||||
case sig := <-signalChan:
|
||||
log.Info("Received signal %s. shutting down", sig)
|
||||
case code = <-exitChan:
|
||||
switch code {
|
||||
case 0:
|
||||
log.Info("Shutting down")
|
||||
default:
|
||||
log.Warn("Shutting down")
|
||||
}
|
||||
}
|
||||
|
||||
log.Close()
|
||||
os.Exit(code)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2014 Unknwon
|
||||
// Copyright 2014 Torkel Ödegaard
|
||||
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
@@ -21,7 +22,13 @@ type RenderOpts struct {
|
||||
|
||||
func RenderToPng(params *RenderOpts) (string, error) {
|
||||
log.Info("PhantomRenderer::renderToPng url %v", params.Url)
|
||||
binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "phantomjs"))
|
||||
|
||||
var executable = "phantomjs"
|
||||
if runtime.GOOS == "windows" {
|
||||
executable = executable + ".exe"
|
||||
}
|
||||
|
||||
binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, executable))
|
||||
scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js"))
|
||||
pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20)))
|
||||
pngPath = pngPath + ".png"
|
||||
|
||||
@@ -35,6 +35,15 @@ func NewLogger(bufLen int64, mode, config string) {
|
||||
}
|
||||
}
|
||||
|
||||
// this helps you work around the performance annoyance mentioned in
|
||||
// https://github.com/grafana/grafana/issues/4055
|
||||
// until we refactor this library completely
|
||||
func Level(level LogLevel) {
|
||||
for i := range loggers {
|
||||
loggers[i].level = level
|
||||
}
|
||||
}
|
||||
|
||||
func Trace(format string, v ...interface{}) {
|
||||
for _, logger := range loggers {
|
||||
logger.Trace(format, v...)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ func (a *ldapAuther) Dial() error {
|
||||
return err
|
||||
} else {
|
||||
if !certPool.AppendCertsFromPEM(pem) {
|
||||
return errors.New("Failed to append CA certficate " + caCertFile)
|
||||
return errors.New("Failed to append CA certificate " + caCertFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func initContextWithAuthProxy(ctx *Context) bool {
|
||||
query := getSignedInUserQueryForProxyAuth(proxyHeaderValue)
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
if err != m.ErrUserNotFound {
|
||||
ctx.Handle(500, "Failed find user specifed in auth proxy header", err)
|
||||
ctx.Handle(500, "Failed to find user specified in auth proxy header", err)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
||||
|
||||
var loader PluginLoader
|
||||
if pluginGoType, exists := PluginTypes[pluginCommon.Type]; !exists {
|
||||
return errors.New("Unkown plugin type " + pluginCommon.Type)
|
||||
return errors.New("Unknown plugin type " + pluginCommon.Type)
|
||||
} else {
|
||||
loader = reflect.New(reflect.TypeOf(pluginGoType)).Interface().(PluginLoader)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user