diff --git a/.gitignore b/.gitignore index 2bd8d89bbd2..e1ba17ed3d5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ config.js .idea/ data/sessions +data/*.db +data/log grafana-pro diff --git a/_vendor/grafana.coffee b/_vendor/grafana.coffee new file mode 100644 index 00000000000..2467fc0ccd6 --- /dev/null +++ b/_vendor/grafana.coffee @@ -0,0 +1,60 @@ +# Description: +# A way to interact with the Google Images API. +# +# Commands: +# hubot image me - The Original. Queries Google Images for and returns a random top result. +# hubot animate me - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead. +# hubot mustache me - Adds a mustache to the specified URL. +# hubot mustache me - Searches Google Images for the specified query and mustaches it. + +module.exports = (robot) -> + robot.hear /grafana (.*)/i, (msg) -> + sendUrl msg.match[1] + + robot.router.get '/hubot/test', (req, res) -> + sendUrl() + res.send 'OK ' + +imageMe = (msg, cb) -> + cb 'http://localhost:3000/render/dashboard/solo/grafana-play-home?from=now-1h&to=now&panelId=4&fullscreen' + +sendUrl = (params) -> + https = require 'https' + querystring = require 'querystring' + opts = params.split(' ') + dashboard = opts[0] + panelId = opts[1] + from = opts[2] + + imageUrl = "http://localhost:3000/render/dashboard/solo/#{dashboard}/?panelId=#{panelId}" + link = "http://localhost:3000/dashboard/db/#{dashboard}/?panelId=#{panelId}&fullscreen" + if from + imageUrl += "&from=#{from}" + link += "&from=#{from}" + + console.log 'imageUrl: ' + imageUrl + + hipchat = {} + hipchat.format = 'json' + hipchat.auth_token = process.env.HUBOT_HIPCHAT_TOKEN + console.log 'token: ' + hipchat.auth_token + + hipchat.room_id = '877465' + hipchat.message = "" + hipchat.from = "hubot" + hipchat.message_format = "html" + + params = querystring.stringify(hipchat) + + path = "/v1/rooms/message/?#{params}" + + data = '' + + https.get {host: 'api.hipchat.com', path: path}, (res) -> + res.on 'data', (chunk) -> + data += chunk.toString() + res.on 'end', () -> + json = JSON.parse(data) + console.log "Hipchat response ", data + + diff --git a/conf/grafana.ini b/conf/grafana.ini index f6438d88bbc..e38f094d39a 100644 --- a/conf/grafana.ini +++ b/conf/grafana.ini @@ -53,6 +53,19 @@ scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis auth_url = https://accounts.google.com/o/oauth2/auth token_url = https://accounts.google.com/o/oauth2/token +[database] +; Either "mysql", "postgres" or "sqlite3", it's your choice +type = sqlite3 +host = 127.0.0.1:3306 +name = grafana +user = root +PASSWD = +; For "postgres" only, either "disable", "require" or "verify-full" +ssl_mode = disable +; For "sqlite3" only +path = data/grafana.db + + [log] root_path = ; Either "console", "file", "conn", "smtp" or "database", default is "console" diff --git a/pkg/cmd/web.go b/pkg/cmd/web.go index 15cc152405f..6b207eaf9ac 100644 --- a/pkg/cmd/web.go +++ b/pkg/cmd/web.go @@ -18,6 +18,7 @@ import ( "github.com/torkelo/grafana-pro/pkg/setting" "github.com/torkelo/grafana-pro/pkg/social" "github.com/torkelo/grafana-pro/pkg/stores/rethink" + "github.com/torkelo/grafana-pro/pkg/stores/sqlstore" ) var CmdWeb = cli.Command{ @@ -68,6 +69,12 @@ func runWeb(*cli.Context) { rethink.Init() social.NewOAuthService() + // init database + sqlstore.LoadModelsConfig() + if err := sqlstore.NewEngine(); err != nil { + log.Fatal(4, "fail to initialize orm engine: %v", err) + } + log.Info("Starting Grafana-Pro v.1-alpha") m := newMacaron() diff --git a/pkg/routes/index.go b/pkg/routes/index.go index 50e4d6edb82..9839d7fd38c 100644 --- a/pkg/routes/index.go +++ b/pkg/routes/index.go @@ -6,6 +6,7 @@ import ( "github.com/torkelo/grafana-pro/pkg/routes/api" "github.com/torkelo/grafana-pro/pkg/routes/apimodel" "github.com/torkelo/grafana-pro/pkg/routes/login" + "github.com/torkelo/grafana-pro/pkg/stores/sqlstore" ) func Register(m *macaron.Macaron) { @@ -32,6 +33,8 @@ func Register(m *macaron.Macaron) { } func Index(ctx *middleware.Context) { + sqlstore.GetAccounts() + ctx.Data["User"] = apimodel.NewCurrentUserDto(ctx.UserAccount) ctx.HTML(200, "index") } diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index c85879bf7a7..7b484decea2 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -148,6 +148,8 @@ func NewConfigContext() { // PhantomJS rendering ImagesDir = "data/png" PhantomDir = "_vendor/phantomjs" + + LogRootPath = Cfg.MustValue("log", "root_path", path.Join(workDir, "/data/log")) } func initSessionService() { diff --git a/pkg/stores/sqlstore/sqlstore.go b/pkg/stores/sqlstore/sqlstore.go new file mode 100644 index 00000000000..90b07dbf92c --- /dev/null +++ b/pkg/stores/sqlstore/sqlstore.go @@ -0,0 +1,109 @@ +package sqlstore + +import ( + "fmt" + "os" + "path" + "strings" + + "github.com/go-xorm/xorm" + _ "github.com/mattn/go-sqlite3" + "github.com/torkelo/grafana-pro/pkg/setting" +) + +var ( + x *xorm.Engine + tables []interface{} + + HasEngine bool + + DbCfg struct { + Type, Host, Name, User, Pwd, Path, SslMode string + } + + UseSQLite3 bool +) + +type AccountDto struct { + Id int64 + Email string `xorm:"UNIQUE NOT NULL"` + Passwd string `xorm:"NOT NULL"` +} + +func init() { + tables = append(tables, new(AccountDto)) +} + +func LoadModelsConfig() { + DbCfg.Type = setting.Cfg.MustValue("database", "type") + if DbCfg.Type == "sqlite3" { + UseSQLite3 = true + } + DbCfg.Host = setting.Cfg.MustValue("database", "host") + DbCfg.Name = setting.Cfg.MustValue("database", "name") + DbCfg.User = setting.Cfg.MustValue("database", "user") + if len(DbCfg.Pwd) == 0 { + DbCfg.Pwd = setting.Cfg.MustValue("database", "passwd") + } + DbCfg.SslMode = setting.Cfg.MustValue("database", "ssl_mode") + DbCfg.Path = setting.Cfg.MustValue("database", "path", "data/grafana.db") +} + +func NewEngine() (err error) { + if err = SetEngine(); err != nil { + return err + } + if err = x.Sync2(tables...); err != nil { + return fmt.Errorf("sync database struct error: %v\n", err) + } + return nil +} + +func SetEngine() (err error) { + x, err = getEngine() + if err != nil { + return fmt.Errorf("models.init(fail to connect to database): %v", err) + } + + logPath := path.Join(setting.LogRootPath, "xorm.log") + os.MkdirAll(path.Dir(logPath), os.ModePerm) + + f, err := os.Create(logPath) + if err != nil { + return fmt.Errorf("models.init(fail to create xorm.log): %v", err) + } + x.Logger = xorm.NewSimpleLogger(f) + + x.ShowSQL = true + x.ShowInfo = true + x.ShowDebug = true + x.ShowErr = true + x.ShowWarn = true + return nil +} + +func getEngine() (*xorm.Engine, error) { + cnnstr := "" + switch DbCfg.Type { + case "mysql": + cnnstr = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", + DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name) + case "postgres": + var host, port = "127.0.0.1", "5432" + fields := strings.Split(DbCfg.Host, ":") + if len(fields) > 0 && len(strings.TrimSpace(fields[0])) > 0 { + host = fields[0] + } + if len(fields) > 1 && len(strings.TrimSpace(fields[1])) > 0 { + port = fields[1] + } + cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s", + DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode) + case "sqlite3": + os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) + cnnstr = "file:" + DbCfg.Path + "?cache=shared&mode=rwc" + default: + return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) + } + return xorm.NewEngine(DbCfg.Type, cnnstr) +} diff --git a/pkg/stores/sqlstore/sqlstore_accounts.go b/pkg/stores/sqlstore/sqlstore_accounts.go new file mode 100644 index 00000000000..7a7b833ff73 --- /dev/null +++ b/pkg/stores/sqlstore/sqlstore_accounts.go @@ -0,0 +1,40 @@ +package sqlstore + +import "github.com/torkelo/grafana-pro/pkg/log" + +func SaveAccount() error { + var err error + + sess := x.NewSession() + defer sess.Close() + + if err = sess.Begin(); err != nil { + return err + } + + u := &AccountDto{ + Email: "asdasdas", + Passwd: "MyPassWd", + } + + if _, err = sess.Insert(u); err != nil { + sess.Rollback() + return err + } else if err = sess.Commit(); err != nil { + return err + } + + return nil +} + +func GetAccounts() { + var resp = make([]*AccountDto, 1) + err := x.Find(&resp) + if err != nil { + log.Error(4, "Error", err) + } + + for _, i := range resp { + log.Info("Item %v", i) + } +}