Merge branch 'master' into cli_db_commands

This commit is contained in:
bergquist
2016-12-09 12:36:05 +01:00
3934 changed files with 228148 additions and 815896 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ func runPluginCommand(command func(commandLine CommandLine) error) func(context
cmd := &contextCommandLine{context}
if err := command(cmd); err != nil {
logger.Errorf("\n%s: ", color.RedString("Error"))
logger.Errorf("%s\n\n", err)
logger.Errorf("%s %s\n\n", color.RedString("✗"), err)
cmd.ShowHelp()
os.Exit(1)
@@ -90,13 +90,12 @@ func InstallPlugin(pluginName, version string, c CommandLine) error {
logger.Infof("%s Installed %s successfully \n", color.GreenString("✔"), plugin.Id)
/* Enable once we need support for downloading depedencies
res, _ := s.ReadPlugin(pluginFolder, pluginName)
for _, v := range res.Dependency.Plugins {
for _, v := range res.Dependencies.Plugins {
InstallPlugin(v.Id, version, c)
log.Infof("Installed dependency: %v ✔\n", v.Id)
logger.Infof("Installed dependency: %v ✔\n", v.Id)
}
*/
return err
}
@@ -53,8 +53,16 @@ func upgradeAllCommand(c CommandLine) error {
for _, p := range pluginsToUpgrade {
logger.Infof("Updating %v \n", p.Id)
s.RemoveInstalledPlugin(pluginsDir, p.Id)
InstallPlugin(p.Id, "", c)
var err error
err = s.RemoveInstalledPlugin(pluginsDir, p.Id)
if err != nil {
return err
}
err = InstallPlugin(p.Id, "", c)
if err != nil {
return err
}
}
return nil
+3
View File
@@ -8,6 +8,7 @@ import (
"github.com/codegangsta/cli"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/commands"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
)
@@ -16,6 +17,8 @@ var version = "master"
func main() {
setupLogging()
services.Init(version)
app := cli.NewApp()
app.Name = "Grafana cli"
app.Usage = ""
+3 -3
View File
@@ -9,11 +9,11 @@ type InstalledPlugin struct {
Name string `json:"name"`
Type string `json:"type"`
Info PluginInfo `json:"info"`
Dependency Dependency `json:"dependencies"`
Info PluginInfo `json:"info"`
Dependencies Dependencies `json:"dependencies"`
}
type Dependency struct {
type Dependencies struct {
GrafanaVersion string `json:"grafanaVersion"`
Plugins []Plugin `json:"plugins"`
}
+87 -20
View File
@@ -1,35 +1,70 @@
package services
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"path"
"time"
"github.com/franela/goreq"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
)
var IoHelper m.IoUtil = IoUtilImp{}
var (
IoHelper m.IoUtil = IoUtilImp{}
HttpClient http.Client
grafanaVersion string
)
func Init(version string) {
grafanaVersion = version
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: false},
}
HttpClient = http.Client{
Timeout: time.Duration(10 * time.Second),
Transport: tr,
}
}
func ListAllPlugins(repoUrl string) (m.PluginRepo, error) {
fullUrl := repoUrl + "/repo"
res, err := goreq.Request{Uri: fullUrl, MaxRedirects: 3}.Do()
body, err := sendRequest(repoUrl, "repo")
if err != nil {
logger.Info("Failed to send request", "error", err)
return m.PluginRepo{}, fmt.Errorf("Failed to send request. error: %v", err)
}
if err != nil {
return m.PluginRepo{}, err
}
if res.StatusCode != 200 {
return m.PluginRepo{}, fmt.Errorf("Could not access %s statuscode %v", fullUrl, res.StatusCode)
}
var resp m.PluginRepo
err = res.Body.FromJsonTo(&resp)
var data m.PluginRepo
err = json.Unmarshal(body, &data)
if err != nil {
return m.PluginRepo{}, errors.New("Could not load plugin data")
logger.Info("Failed to unmarshal graphite response error: %v", err)
return m.PluginRepo{}, err
}
return resp, nil
return data, nil
}
func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) {
@@ -88,21 +123,53 @@ func RemoveInstalledPlugin(pluginPath, pluginName string) error {
}
func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {
fullUrl := repoUrl + "/repo/" + pluginId
body, err := sendRequest(repoUrl, "repo", pluginId)
if err != nil {
logger.Info("Failed to send request", "error", err)
return m.Plugin{}, fmt.Errorf("Failed to send request. error: %v", err)
}
res, err := goreq.Request{Uri: fullUrl, MaxRedirects: 3}.Do()
if err != nil {
return m.Plugin{}, err
}
if res.StatusCode != 200 {
return m.Plugin{}, fmt.Errorf("Could not access %s statuscode %v", fullUrl, res.StatusCode)
}
var resp m.Plugin
err = res.Body.FromJsonTo(&resp)
var data m.Plugin
err = json.Unmarshal(body, &data)
if err != nil {
return m.Plugin{}, errors.New("Could not load plugin data")
logger.Info("Failed to unmarshal graphite response error: %v", err)
return m.Plugin{}, err
}
return resp, nil
return data, nil
}
func sendRequest(repoUrl string, subPaths ...string) ([]byte, error) {
u, _ := url.Parse(repoUrl)
for _, v := range subPaths {
u.Path = path.Join(u.Path, v)
}
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
req.Header.Set("grafana-version", grafanaVersion)
req.Header.Set("User-Agent", "grafana "+grafanaVersion)
if err != nil {
return []byte{}, err
}
res, err := HttpClient.Do(req)
if err != nil {
return []byte{}, err
}
if res.StatusCode/100 != 2 {
return []byte{}, fmt.Errorf("Api returned invalid status: %s", res.Status)
}
body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
return body, err
}
+19 -38
View File
@@ -13,18 +13,20 @@ import (
"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/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/social"
_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
_ "github.com/grafana/grafana/pkg/tsdb/graphite"
_ "github.com/grafana/grafana/pkg/tsdb/influxdb"
_ "github.com/grafana/grafana/pkg/tsdb/opentsdb"
_ "github.com/grafana/grafana/pkg/tsdb/prometheus"
_ "github.com/grafana/grafana/pkg/tsdb/testdata"
)
var version = "3.1.0"
var version = "4.1.0"
var commit = "NA"
var buildstamp string
var build_date string
@@ -55,25 +57,8 @@ func main() {
setting.BuildCommit = commit
setting.BuildStamp = buildstampInt64
go listenToSystemSignels()
flag.Parse()
writePIDFile()
initRuntime()
metrics.Init()
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)
}
StartServer()
exitChan <- 0
server := NewGrafanaServer()
server.Start()
}
func initRuntime() {
@@ -91,7 +76,9 @@ func initRuntime() {
logger.Info("Starting Grafana", "version", version, "commit", commit, "compiled", time.Unix(setting.BuildStamp, 0))
setting.LogConfigurationInfo()
}
func initSql() {
sqlstore.NewEngine()
sqlstore.EnsureAdminUser()
}
@@ -114,24 +101,18 @@ func writePIDFile() {
}
}
func listenToSystemSignels() {
func listenToSystemSignals(server models.GrafanaServer) {
signalChan := make(chan os.Signal, 1)
ignoreChan := make(chan os.Signal, 1)
code := 0
signal.Notify(ignoreChan, syscall.SIGHUP)
signal.Notify(signalChan, os.Interrupt, os.Kill, syscall.SIGTERM)
select {
case sig := <-signalChan:
log.Info("Received signal %s. shutting down", sig)
server.Shutdown(0, fmt.Sprintf("system signal: %s", sig))
case code = <-exitChan:
switch code {
case 0:
log.Info("Shutting down")
default:
log.Warn("Shutting down")
}
server.Shutdown(code, "startup error")
}
log.Close()
os.Exit(code)
}
+150
View File
@@ -0,0 +1,150 @@
package main
import (
"context"
"fmt"
"net/http"
"os"
"time"
"gopkg.in/macaron.v1"
"golang.org/x/sync/errgroup"
"github.com/grafana/grafana/pkg/api"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/cleanup"
"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/setting"
"github.com/grafana/grafana/pkg/social"
)
func NewGrafanaServer() models.GrafanaServer {
rootCtx, shutdownFn := context.WithCancel(context.Background())
childRoutines, childCtx := errgroup.WithContext(rootCtx)
return &GrafanaServerImpl{
context: childCtx,
shutdownFn: shutdownFn,
childRoutines: childRoutines,
log: log.New("server"),
}
}
type GrafanaServerImpl struct {
context context.Context
shutdownFn context.CancelFunc
childRoutines *errgroup.Group
log log.Logger
}
func (g *GrafanaServerImpl) Start() {
go listenToSystemSignals(g)
writePIDFile()
initRuntime()
initSql()
metrics.Init()
search.Init()
login.Init()
social.NewOAuthService()
eventpublisher.Init()
plugins.Init()
// init alerting
if setting.ExecuteAlerts {
engine := alerting.NewEngine()
g.childRoutines.Go(func() error { return engine.Run(g.context) })
}
// cleanup service
cleanUpService := cleanup.NewCleanUpService()
g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) })
if err := notifications.Init(); err != nil {
g.log.Error("Notification service failed to initialize", "erro", err)
g.Shutdown(1, "Startup failed")
return
}
g.startHttpServer()
}
func (g *GrafanaServerImpl) startHttpServer() {
logger = log.New("http.server")
var err error
m := newMacaron()
api.Register(m)
listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
g.log.Info("Initializing HTTP Server", "address", listenAddr, "protocol", setting.Protocol, "subUrl", setting.AppSubUrl)
switch setting.Protocol {
case setting.HTTP:
err = http.ListenAndServe(listenAddr, m)
case setting.HTTPS:
err = ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
default:
g.log.Error("Invalid protocol", "protocol", setting.Protocol)
g.Shutdown(1, "Startup failed")
}
if err != nil {
g.log.Error("Fail to start server", "error", err)
g.Shutdown(1, "Startup failed")
return
}
}
func (g *GrafanaServerImpl) Shutdown(code int, reason string) {
g.log.Info("Shutdown started", "code", code, "reason", reason)
g.shutdownFn()
err := g.childRoutines.Wait()
g.log.Info("Shutdown completed", "reason", err)
log.Close()
os.Exit(code)
}
func ListenAndServeTLS(listenAddr, certfile, keyfile string, m *macaron.Macaron) error {
if certfile == "" {
return fmt.Errorf("cert_file cannot be empty when using HTTPS")
}
if keyfile == "" {
return fmt.Errorf("cert_key cannot be empty when using HTTPS")
}
if _, err := os.Stat(setting.CertFile); os.IsNotExist(err) {
return fmt.Errorf(`Cannot find SSL cert_file at %v`, setting.CertFile)
}
if _, err := os.Stat(setting.KeyFile); os.IsNotExist(err) {
return fmt.Errorf(`Cannot find SSL key_file at %v`, setting.KeyFile)
}
return http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
}
// implement context.Context
func (g *GrafanaServerImpl) Deadline() (deadline time.Time, ok bool) {
return g.context.Deadline()
}
func (g *GrafanaServerImpl) Done() <-chan struct{} {
return g.context.Done()
}
func (g *GrafanaServerImpl) Err() error {
return g.context.Err()
}
func (g *GrafanaServerImpl) Value(key interface{}) interface{} {
return g.context.Value(key)
}
+10 -7
View File
@@ -6,7 +6,6 @@ package main
import (
"fmt"
"net/http"
"os"
"path"
"gopkg.in/macaron.v1"
@@ -47,13 +46,15 @@ func newMacaron() *macaron.Macaron {
Delims: macaron.Delims{Left: "[[", Right: "]]"},
}))
m.Use(middleware.GetContextHandler())
m.Use(middleware.Sessioner(&setting.SessionOptions))
m.Use(middleware.RequestMetrics())
// needs to be after context handler
if setting.EnforceDomain {
m.Use(middleware.ValidateHostHeader(setting.Domain))
}
m.Use(middleware.GetContextHandler())
m.Use(middleware.Sessioner(&setting.SessionOptions))
return m
}
@@ -78,7 +79,7 @@ func mapStatic(m *macaron.Macaron, rootDir string, dir string, prefix string) {
))
}
func StartServer() {
func StartServer() int {
logger = log.New("server")
var err error
@@ -94,11 +95,13 @@ func StartServer() {
err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
default:
logger.Error("Invalid protocol", "protocol", setting.Protocol)
os.Exit(1)
return 1
}
if err != nil {
logger.Error("Fail to start server", "error", err)
os.Exit(1)
return 1
}
return 0
}