core config var changes, log changes

pull/342/head
Hunter Long 2019-12-30 00:08:51 -08:00
parent 77e4bbe728
commit 12b8ad73a3
19 changed files with 172 additions and 133 deletions

View File

@ -7,7 +7,7 @@ XGO=xgo -go $(GOVERSION) --dest=build
BUILDVERSION=-ldflags "-X main.VERSION=${VERSION} -X main.COMMIT=$(TRAVIS_COMMIT)" BUILDVERSION=-ldflags "-X main.VERSION=${VERSION} -X main.COMMIT=$(TRAVIS_COMMIT)"
TRVIS_SECRET=CAVxMvW04wS/APA6QGjlWjLfTx5hc+TWwCKuBkMV2MioZSQGOTQBC4nITySUwepAFY25mI8zNV5oROOKzG0FxYvr2iIqKDkTTdVF1+XS2uyHfEKlsWMPErcqkGjRksDil75Pckz15uvvOYPndetK2QiamQkSf9U8dUJgzrPuV+UOFj6RO/kkEWhzmoyTdVdwIRKmiL8jINkvvFOWCAfg3WlBmucgYHHqjqeTn1kSeUJ+DV9lF8+ENq+74GZrnsq26UtskJexywDeFhhUYjWEvOFXQ19txB/JrvdZ2KSkYeuhHr1ZxlENSpQ/rySQqBvg7+XAl1RhQlL5V7/feXA+I/COqNYG5KqbDgeSUwGkZIumz1ITi24Lz4xATG5hnuRQkOIaO8/FGHAeQxU0JcdWlzS8M5RpvpN9tT12XSFDPYswFmkO+gGSEpu+2gSEbiaX7qocLLvZiMpkQxfOmItaUW5ZMXRvTWijhQTb2nyPOQ9JEabuAtAUrCwe7Enmc8P8ZasNZaJLJO53iQ8FyzrNFyAFwY5F87OQ/v3Hnjv0ADG8fDc4VUxlj8TweuRzETT8U2hchxqnK4BON2WMSj4d1V96pDuzb5fArtq5PTbI4VB7mZPriXYZEiKdfLEIufOYhg7uKdNRekMLkuJRr+ttH0Gyb+lILzSiHMHwxOH5bfM= TRVIS_SECRET=CAVxMvW04wS/APA6QGjlWjLfTx5hc+TWwCKuBkMV2MioZSQGOTQBC4nITySUwepAFY25mI8zNV5oROOKzG0FxYvr2iIqKDkTTdVF1+XS2uyHfEKlsWMPErcqkGjRksDil75Pckz15uvvOYPndetK2QiamQkSf9U8dUJgzrPuV+UOFj6RO/kkEWhzmoyTdVdwIRKmiL8jINkvvFOWCAfg3WlBmucgYHHqjqeTn1kSeUJ+DV9lF8+ENq+74GZrnsq26UtskJexywDeFhhUYjWEvOFXQ19txB/JrvdZ2KSkYeuhHr1ZxlENSpQ/rySQqBvg7+XAl1RhQlL5V7/feXA+I/COqNYG5KqbDgeSUwGkZIumz1ITi24Lz4xATG5hnuRQkOIaO8/FGHAeQxU0JcdWlzS8M5RpvpN9tT12XSFDPYswFmkO+gGSEpu+2gSEbiaX7qocLLvZiMpkQxfOmItaUW5ZMXRvTWijhQTb2nyPOQ9JEabuAtAUrCwe7Enmc8P8ZasNZaJLJO53iQ8FyzrNFyAFwY5F87OQ/v3Hnjv0ADG8fDc4VUxlj8TweuRzETT8U2hchxqnK4BON2WMSj4d1V96pDuzb5fArtq5PTbI4VB7mZPriXYZEiKdfLEIufOYhg7uKdNRekMLkuJRr+ttH0Gyb+lILzSiHMHwxOH5bfM=
PUBLISH_BODY='{ "request": { "branch": "master", "message": "Homebrew update version v${VERSION}", "config": { "env": { "VERSION": "${VERSION}", "COMMIT": "$(TRAVIS_COMMIT)" } } } }' PUBLISH_BODY='{ "request": { "branch": "master", "message": "Homebrew update version v${VERSION}", "config": { "env": { "VERSION": "${VERSION}", "COMMIT": "$(TRAVIS_COMMIT)" } } } }'
TRAVIS_BUILD_CMD='{ "request": { "branch": "master", "message": "Compile master for Statping v${VERSION}", "config": {"merge_mode": ["deep_merge"], "os": [ "linux" ], "language": "go", "go": [ "${GOVERSION}" ], "go_import_path": "github.com/hunterlong/statping", "install": true, "sudo": "required", "services": [ "docker" ], "env": { "VERSION": "${VERSION}" }, "matrix": { "allow_failures": [ { "go": "master" } ], "fast_finish": true }, "before_deploy": [ "git config --local user.name \"hunterlong\"", "git config --local user.email \"info@socialeck.com\"", "git tag v$(VERSION) --force"], "deploy": [ { "provider": "releases", "api_key": {"secret": "$(TRVIS_SECRET)"}, "file_glob": true, "file": "build/*", "skip_cleanup": true } ], "notifications": { "email": false }, "before_script": ["gem install sass"], "script": [ "travis_wait 30 docker pull crazymax/xgo:$(GOVERSION)", "make release" ], "after_success": [], "after_deploy": [ "make publish-homebrew" ] } } }' TRAVIS_BUILD_CMD='{ "request": { "branch": "master", "message": "Compile master for Statping v${VERSION}", "config": { "os": [ "linux" ], "language": "go", "go": [ "${GOVERSION}" ], "go_import_path": "github.com/hunterlong/statping", "install": true, "sudo": "required", "services": [ "docker" ], "env": { "VERSION": "${VERSION}" }, "matrix": { "allow_failures": [ { "go": "master" } ], "fast_finish": true }, "before_deploy": [ "git config --local user.name \"hunterlong\"", "git config --local user.email \"info@socialeck.com\"", "git tag v$(VERSION) --force"], "deploy": [ { "provider": "releases", "api_key": {"secret": "$(TRVIS_SECRET)"}, "file_glob": true, "file": "build/*", "skip_cleanup": true, "on": {"branch": "master"} } ], "notifications": { "email": false }, "before_script": ["gem install sass"], "script": [ "travis_wait 30 docker pull crazymax/xgo:$(GOVERSION)", "make release" ], "after_success": [], "after_deploy": [ "make publish-homebrew" ] } } }'
TEST_DIR=$(GOPATH)/src/github.com/hunterlong/statping TEST_DIR=$(GOPATH)/src/github.com/hunterlong/statping
PATH:=/usr/local/bin:$(GOPATH)/bin:$(PATH) PATH:=/usr/local/bin:$(GOPATH)/bin:$(PATH)

View File

@ -88,17 +88,17 @@ func catchCLI(args []string) error {
return err return err
} }
fmt.Printf("Statping v%v Exporting Static 'index.html' page...\n", VERSION) fmt.Printf("Statping v%v Exporting Static 'index.html' page...\n", VERSION)
if core.Configs, err = core.LoadConfigFile(dir); err != nil { if core.CoreApp.Config, err = core.LoadConfigFile(dir); err != nil {
utils.Log.Errorln("config.yml file not found") log.Errorln("config.yml file not found")
return err return err
} }
indexSource := ExportIndexHTML() indexSource := ExportIndexHTML()
//core.CloseDB() //core.CloseDB()
if err = utils.SaveFile(dir+"/index.html", indexSource); err != nil { if err = utils.SaveFile(dir+"/index.html", indexSource); err != nil {
utils.Log.Errorln(err) log.Errorln(err)
return err return err
} }
utils.Log.Infoln("Exported Statping index page: 'index.html'") log.Infoln("Exported Statping index page: 'index.html'")
case "help": case "help":
HelpEcho() HelpEcho()
return errors.New("end") return errors.New("end")
@ -111,10 +111,10 @@ func catchCLI(args []string) error {
if err = runAssets(); err != nil { if err = runAssets(); err != nil {
return err return err
} }
if core.Configs, err = core.LoadConfigFile(dir); err != nil { if core.CoreApp.Config, err = core.LoadConfigFile(dir); err != nil {
return err return err
} }
if err = core.Configs.Connect(false, dir); err != nil { if err = core.CoreApp.Connect(false, dir); err != nil {
return err return err
} }
if data, err = core.ExportSettings(); err != nil { if data, err = core.ExportSettings(); err != nil {
@ -147,7 +147,7 @@ func catchCLI(args []string) error {
if err := runAssets(); err != nil { if err := runAssets(); err != nil {
return err return err
} }
utils.Log.Infoln("Running 1 time and saving to database...") log.Infoln("Running 1 time and saving to database...")
runOnce() runOnce()
//core.CloseDB() //core.CloseDB()
fmt.Println("Check is complete.") fmt.Println("Check is complete.")
@ -162,7 +162,7 @@ func catchCLI(args []string) error {
} }
envs, err := godotenv.Read(".env") envs, err := godotenv.Read(".env")
if err != nil { if err != nil {
utils.Log.Errorln("No .env file found in current directory.") log.Errorln("No .env file found in current directory.")
return err return err
} }
for k, e := range envs { for k, e := range envs {
@ -177,7 +177,7 @@ func catchCLI(args []string) error {
// ExportIndexHTML returns the HTML of the index page as a string // ExportIndexHTML returns the HTML of the index page as a string
func ExportIndexHTML() []byte { func ExportIndexHTML() []byte {
source.Assets() source.Assets()
core.Configs.Connect(false, utils.Directory) core.CoreApp.Connect(false, utils.Directory)
core.CoreApp.SelectAllServices(false) core.CoreApp.SelectAllServices(false)
core.CoreApp.UseCdn = types.NewNullBool(true) core.CoreApp.UseCdn = types.NewNullBool(true)
for _, srv := range core.CoreApp.Services { for _, srv := range core.CoreApp.Services {
@ -208,13 +208,13 @@ func updateDisplay() error {
// runOnce will initialize the Statping application and check each service 1 time, will not run HTTP server // runOnce will initialize the Statping application and check each service 1 time, will not run HTTP server
func runOnce() { func runOnce() {
var err error var err error
core.Configs, err = core.LoadConfigFile(utils.Directory) core.CoreApp.Config, err = core.LoadConfigFile(utils.Directory)
if err != nil { if err != nil {
utils.Log.Errorln("config.yml file not found") log.Errorln("config.yml file not found")
} }
err = core.Configs.Connect(false, utils.Directory) err = core.CoreApp.Connect(false, utils.Directory)
if err != nil { if err != nil {
utils.Log.Errorln(err) log.Errorln(err)
} }
core.CoreApp, err = core.SelectCore() core.CoreApp, err = core.SelectCore()
if err != nil { if err != nil {
@ -222,7 +222,7 @@ func runOnce() {
} }
_, err = core.CoreApp.SelectAllServices(true) _, err = core.CoreApp.SelectAllServices(true)
if err != nil { if err != nil {
utils.Log.Errorln(err) log.Errorln(err)
} }
for _, out := range core.CoreApp.Services { for _, out := range core.CoreApp.Services {
out.Check(true) out.Check(true)

View File

@ -39,6 +39,7 @@ var (
envFile string envFile string
verboseMode int verboseMode int
port int port int
log = utils.Log.WithField("type", "cmd")
) )
func init() { func init() {
@ -52,7 +53,7 @@ func parseFlags() {
flag.StringVar(&ipAddress, "ip", "0.0.0.0", "IP address to run the Statping HTTP server") flag.StringVar(&ipAddress, "ip", "0.0.0.0", "IP address to run the Statping HTTP server")
flag.StringVar(&envFile, "env", "", "IP address to run the Statping HTTP server") flag.StringVar(&envFile, "env", "", "IP address to run the Statping HTTP server")
flag.IntVar(&port, "port", 8080, "Port to run the HTTP server") flag.IntVar(&port, "port", 8080, "Port to run the HTTP server")
flag.IntVar(&verboseMode, "verbose", 1, "Run in verbose mode to see detailed logs (1 - 4)") flag.IntVar(&verboseMode, "verbose", 2, "Run in verbose mode to see detailed logs (1 - 4)")
flag.Parse() flag.Parse()
if os.Getenv("PORT") != "" { if os.Getenv("PORT") != "" {
@ -75,8 +76,7 @@ func main() {
source.Assets() source.Assets()
utils.VerboseMode = verboseMode utils.VerboseMode = verboseMode
if err := utils.InitLogs(); err != nil { if err := utils.InitLogs(); err != nil {
fmt.Printf("Statping Log Error: \n %v\n", err) log.Fatalln("Statping Log Error: \n %v\n", err)
os.Exit(2)
} }
args := flag.Args() args := flag.Args()
@ -90,16 +90,18 @@ func main() {
os.Exit(1) os.Exit(1)
} }
} }
utils.Log.Info(fmt.Sprintf("Starting Statping v%v", VERSION)) log.Info(fmt.Sprintf("Starting Statping v%v", VERSION))
updateDisplay() updateDisplay()
core.Configs, err = core.LoadConfigFile(utils.Directory) configs, err := core.LoadConfigFile(utils.Directory)
if err != nil { if err != nil {
utils.Log.Errorln(err) log.Errorln(err)
core.SetupMode = true core.SetupMode = true
utils.Log.Infoln(handlers.RunHTTPServer(ipAddress, port)) if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
os.Exit(1) log.Fatalln(err)
}
} }
core.CoreApp.Config = configs
mainProcess() mainProcess()
} }
@ -122,7 +124,7 @@ func sigterm() {
func loadDotEnvs() error { func loadDotEnvs() error {
err := godotenv.Load(envFile) err := godotenv.Load(envFile)
if err == nil { if err == nil {
utils.Log.Infoln("Environment file '.env' Loaded") log.Infoln("Environment file '.env' Loaded")
} }
return err return err
} }
@ -131,15 +133,16 @@ func loadDotEnvs() error {
func mainProcess() { func mainProcess() {
dir := utils.Directory dir := utils.Directory
var err error var err error
err = core.Configs.Connect(false, dir) err = core.CoreApp.Connect(false, dir)
if err != nil { if err != nil {
utils.Log.Errorln(fmt.Sprintf("could not connect to database: %v", err)) log.Errorln(fmt.Sprintf("could not connect to database: %v", err))
} }
core.Configs.MigrateDatabase() core.CoreApp.MigrateDatabase()
core.InitApp() core.InitApp()
if !core.SetupMode { if !core.SetupMode {
plugin.LoadPlugins() plugin.LoadPlugins()
fmt.Println(handlers.RunHTTPServer(ipAddress, port)) if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
os.Exit(1) log.Fatalln(err)
}
} }
} }

View File

@ -31,12 +31,13 @@ type ErrorResponse struct {
} }
// LoadConfigFile will attempt to load the 'config.yml' file in a specific directory // LoadConfigFile will attempt to load the 'config.yml' file in a specific directory
func LoadConfigFile(directory string) (*DbConfig, error) { func LoadConfigFile(directory string) (*types.DbConfig, error) {
var configs *DbConfig var configs *types.DbConfig
if os.Getenv("DB_CONN") != "" { if os.Getenv("DB_CONN") != "" {
log.Infoln("DB_CONN environment variable was found, waiting for database...") log.Infoln("DB_CONN environment variable was found, waiting for database...")
return LoadUsingEnv() return LoadUsingEnv()
} }
log.Debugln("attempting to read config file at: " + directory + "/config.yml")
file, err := ioutil.ReadFile(directory + "/config.yml") file, err := ioutil.ReadFile(directory + "/config.yml")
if err != nil { if err != nil {
return nil, errors.New("config.yml file not found at " + directory + "/config.yml - starting in setup mode") return nil, errors.New("config.yml file not found at " + directory + "/config.yml - starting in setup mode")
@ -45,12 +46,13 @@ func LoadConfigFile(directory string) (*DbConfig, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
Configs = configs log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + directory + "/config.yml")
return Configs, err CoreApp.Config = configs
return configs, err
} }
// LoadUsingEnv will attempt to load database configs based on environment variables. If DB_CONN is set if will force this function. // LoadUsingEnv will attempt to load database configs based on environment variables. If DB_CONN is set if will force this function.
func LoadUsingEnv() (*DbConfig, error) { func LoadUsingEnv() (*types.DbConfig, error) {
Configs, err := EnvToConfig() Configs, err := EnvToConfig()
if err != nil { if err != nil {
return Configs, err return Configs, err
@ -61,21 +63,20 @@ func LoadUsingEnv() (*DbConfig, error) {
} else { } else {
CoreApp.Domain = os.Getenv("DOMAIN") CoreApp.Domain = os.Getenv("DOMAIN")
} }
CoreApp.DbConnection = Configs.DbConn
CoreApp.UseCdn = types.NewNullBool(os.Getenv("USE_CDN") == "true") CoreApp.UseCdn = types.NewNullBool(os.Getenv("USE_CDN") == "true")
err = Configs.Connect(true, utils.Directory) err = CoreApp.Connect(true, utils.Directory)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return nil, err return nil, err
} }
Configs.Save() CoreApp.SaveConfig(Configs)
exists := DbSession.HasTable("core") exists := DbSession.HasTable("core")
if !exists { if !exists {
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!")) log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
Configs.DropDatabase() CoreApp.DropDatabase()
Configs.CreateDatabase() CoreApp.CreateDatabase()
CoreApp, err = Configs.InsertCore() CoreApp, err = CoreApp.InsertCore(Configs)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
} }
@ -118,24 +119,23 @@ func DefaultPort(db string) int64 {
} }
// EnvToConfig converts environment variables to a DbConfig variable // EnvToConfig converts environment variables to a DbConfig variable
func EnvToConfig() (*DbConfig, error) { func EnvToConfig() (*types.DbConfig, error) {
Configs = new(DbConfig)
var err error var err error
if os.Getenv("DB_CONN") == "" { if os.Getenv("DB_CONN") == "" {
return Configs, errors.New("Missing DB_CONN environment variable") return nil, errors.New("Missing DB_CONN environment variable")
} }
if os.Getenv("DB_CONN") != "sqlite" { if os.Getenv("DB_CONN") != "sqlite" {
if os.Getenv("DB_HOST") == "" { if os.Getenv("DB_HOST") == "" {
return Configs, errors.New("Missing DB_HOST environment variable") return nil, errors.New("Missing DB_HOST environment variable")
} }
if os.Getenv("DB_USER") == "" { if os.Getenv("DB_USER") == "" {
return Configs, errors.New("Missing DB_USER environment variable") return nil, errors.New("Missing DB_USER environment variable")
} }
if os.Getenv("DB_PASS") == "" { if os.Getenv("DB_PASS") == "" {
return Configs, errors.New("Missing DB_PASS environment variable") return nil, errors.New("Missing DB_PASS environment variable")
} }
if os.Getenv("DB_DATABASE") == "" { if os.Getenv("DB_DATABASE") == "" {
return Configs, errors.New("Missing DB_DATABASE environment variable") return nil, errors.New("Missing DB_DATABASE environment variable")
} }
} }
port := utils.ToInt(os.Getenv("DB_PORT")) port := utils.ToInt(os.Getenv("DB_PORT"))
@ -161,7 +161,7 @@ func EnvToConfig() (*DbConfig, error) {
adminPass = "admin" adminPass = "admin"
} }
Configs = &DbConfig{ configs := &types.DbConfig{
DbConn: os.Getenv("DB_CONN"), DbConn: os.Getenv("DB_CONN"),
DbHost: os.Getenv("DB_HOST"), DbHost: os.Getenv("DB_HOST"),
DbUser: os.Getenv("DB_USER"), DbUser: os.Getenv("DB_USER"),
@ -178,7 +178,8 @@ func EnvToConfig() (*DbConfig, error) {
Location: utils.Directory, Location: utils.Directory,
SqlFile: os.Getenv("SQL_FILE"), SqlFile: os.Getenv("SQL_FILE"),
} }
return Configs, err CoreApp.Config = configs
return configs, err
} }
// SampleData runs all the sample data for a new Statping installation // SampleData runs all the sample data for a new Statping installation
@ -194,7 +195,8 @@ func SampleData() error {
// DeleteConfig will delete the 'config.yml' file // DeleteConfig will delete the 'config.yml' file
func DeleteConfig() error { func DeleteConfig() error {
err := os.Remove(utils.Directory + "/config.yml") log.Debugln("deleting config yaml file", utils.Directory+"/config.yml")
err := utils.DeleteFile(utils.Directory + "/config.yml")
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return err return err

View File

@ -36,10 +36,9 @@ type Core struct {
} }
var ( var (
Configs *DbConfig // Configs holds all of the config.yml and database info CoreApp *Core // CoreApp is a global variable that contains many elements
CoreApp *Core // CoreApp is a global variable that contains many elements SetupMode bool // SetupMode will be true if Statping does not have a database connection
SetupMode bool // SetupMode will be true if Statping does not have a database connection VERSION string // VERSION is set on build automatically by setting a -ldflag
VERSION string // VERSION is set on build automatically by setting a -ldflag
log = utils.Log.WithField("type", "core") log = utils.Log.WithField("type", "core")
) )
@ -49,9 +48,10 @@ func init() {
// NewCore return a new *core.Core struct // NewCore return a new *core.Core struct
func NewCore() *Core { func NewCore() *Core {
CoreApp = new(Core) CoreApp = &Core{&types.Core{
CoreApp.Core = new(types.Core) Started: time.Now(),
CoreApp.Started = time.Now() },
}
return CoreApp return CoreApp
} }
@ -69,12 +69,13 @@ func InitApp() {
AttachNotifiers() AttachNotifiers()
CoreApp.Notifications = notifier.AllCommunications CoreApp.Notifications = notifier.AllCommunications
go DatabaseMaintence() go DatabaseMaintence()
SetupMode = false
} }
// InsertNotifierDB inject the Statping database instance to the Notifier package // InsertNotifierDB inject the Statping database instance to the Notifier package
func InsertNotifierDB() error { func InsertNotifierDB() error {
if DbSession == nil { if DbSession == nil {
err := Configs.Connect(false, utils.Directory) err := CoreApp.Connect(false, utils.Directory)
if err != nil { if err != nil {
return errors.New("database connection has not been created") return errors.New("database connection has not been created")
} }
@ -159,7 +160,6 @@ func SelectCore() (*Core, error) {
if db.Error != nil { if db.Error != nil {
return nil, db.Error return nil, db.Error
} }
CoreApp.DbConnection = Configs.DbConn
CoreApp.Version = VERSION CoreApp.Version = VERSION
CoreApp.UseCdn = types.NewNullBool(os.Getenv("USE_CDN") == "true") CoreApp.UseCdn = types.NewNullBool(os.Getenv("USE_CDN") == "true")
return CoreApp, db.Error return CoreApp, db.Error

View File

@ -68,7 +68,7 @@ func TestLoadDbConfig(t *testing.T) {
} }
func TestDbConnection(t *testing.T) { func TestDbConnection(t *testing.T) {
err := Configs.Connect(false, dir) err := CoreApp.Connect(false, dir)
assert.Nil(t, err) assert.Nil(t, err)
} }
@ -77,7 +77,7 @@ func TestDropDatabase(t *testing.T) {
if skipNewDb { if skipNewDb {
t.SkipNow() t.SkipNow()
} }
err := Configs.DropDatabase() err := CoreApp.DropDatabase()
assert.Nil(t, err) assert.Nil(t, err)
} }
@ -86,13 +86,13 @@ func TestSeedSchemaDatabase(t *testing.T) {
if skipNewDb { if skipNewDb {
t.SkipNow() t.SkipNow()
} }
err := Configs.CreateDatabase() err := CoreApp.CreateDatabase()
assert.Nil(t, err) assert.Nil(t, err)
} }
func TestMigrateDatabase(t *testing.T) { func TestMigrateDatabase(t *testing.T) {
t.SkipNow() t.SkipNow()
err := Configs.MigrateDatabase() err := CoreApp.MigrateDatabase()
assert.Nil(t, err) assert.Nil(t, err)
} }
@ -103,9 +103,9 @@ func TestSeedDatabase(t *testing.T) {
} }
func TestReLoadDbConfig(t *testing.T) { func TestReLoadDbConfig(t *testing.T) {
err := Configs.Connect(false, dir) err := CoreApp.Connect(false, dir)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, "sqlite", Configs.DbConn) assert.Equal(t, "sqlite", CoreApp.Config.DbConn)
} }
func TestSelectCore(t *testing.T) { func TestSelectCore(t *testing.T) {

View File

@ -101,7 +101,7 @@ func incidentsUpdatesDB() *gorm.DB {
// HitsBetween returns the gorm database query for a collection of service hits between a time range // HitsBetween returns the gorm database query for a collection of service hits between a time range
func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB { func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB {
selector := Dbtimestamp(group, column) selector := Dbtimestamp(group, column)
if CoreApp.DbConnection == "postgres" { if CoreApp.Config.DbConn == "postgres" {
return hitsDB().Select(selector).Where("service = ? AND created_at BETWEEN ? AND ?", s.Id, t1.UTC().Format(types.TIME), t2.UTC().Format(types.TIME)) return hitsDB().Select(selector).Where("service = ? AND created_at BETWEEN ? AND ?", s.Id, t1.UTC().Format(types.TIME), t2.UTC().Format(types.TIME))
} else { } else {
return hitsDB().Select(selector).Where("service = ? AND created_at BETWEEN ? AND ?", s.Id, t1.UTC().Format(types.TIME_DAY), t2.UTC().Format(types.TIME_DAY)) return hitsDB().Select(selector).Where("service = ? AND created_at BETWEEN ? AND ?", s.Id, t1.UTC().Format(types.TIME_DAY), t2.UTC().Format(types.TIME_DAY))
@ -171,24 +171,24 @@ func (u *Message) AfterFind() (err error) {
} }
// InsertCore create the single row for the Core settings in Statping // InsertCore create the single row for the Core settings in Statping
func (db *DbConfig) InsertCore() (*Core, error) { func (c *Core) InsertCore(db *types.DbConfig) (*Core, error) {
CoreApp = &Core{Core: &types.Core{ CoreApp = &Core{Core: &types.Core{
Name: db.Project, Name: db.Project,
Description: db.Description, Description: db.Description,
Config: "config.yml", ConfigFile: "config.yml",
ApiKey: utils.NewSHA1Hash(9), ApiKey: utils.NewSHA1Hash(9),
ApiSecret: utils.NewSHA1Hash(16), ApiSecret: utils.NewSHA1Hash(16),
Domain: db.Domain, Domain: db.Domain,
MigrationId: time.Now().Unix(), MigrationId: time.Now().Unix(),
Config: db,
}} }}
CoreApp.DbConnection = db.DbConn
query := coreDB().Create(&CoreApp) query := coreDB().Create(&CoreApp)
return CoreApp, query.Error return CoreApp, query.Error
} }
func findDbFile() string { func findDbFile() string {
if Configs.SqlFile != "" { if CoreApp.Config.SqlFile != "" {
return Configs.SqlFile return CoreApp.Config.SqlFile
} }
filename := types.SqliteFilename filename := types.SqliteFilename
err := filepath.Walk(utils.Directory, func(path string, info os.FileInfo, err error) error { err := filepath.Walk(utils.Directory, func(path string, info os.FileInfo, err error) error {
@ -207,16 +207,16 @@ func findDbFile() string {
} }
// Connect will attempt to connect to the sqlite, postgres, or mysql database // Connect will attempt to connect to the sqlite, postgres, or mysql database
func (db *DbConfig) Connect(retry bool, location string) error { func (c *Core) Connect(retry bool, location string) error {
postgresSSL := os.Getenv("POSTGRES_SSLMODE") postgresSSL := os.Getenv("POSTGRES_SSLMODE")
if DbSession != nil { if DbSession != nil {
return nil return nil
} }
var conn, dbType string var conn, dbType string
var err error var err error
dbType = Configs.DbConn dbType = CoreApp.Config.DbConn
if Configs.DbPort == 0 { if CoreApp.Config.DbPort == 0 {
Configs.DbPort = DefaultPort(dbType) CoreApp.Config.DbPort = DefaultPort(dbType)
} }
switch dbType { switch dbType {
case "sqlite": case "sqlite":
@ -224,27 +224,30 @@ func (db *DbConfig) Connect(retry bool, location string) error {
conn = sqlFilename conn = sqlFilename
dbType = "sqlite3" dbType = "sqlite3"
case "mysql": case "mysql":
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort) host := fmt.Sprintf("%v:%v", CoreApp.Config.DbHost, CoreApp.Config.DbPort)
conn = fmt.Sprintf("%v:%v@tcp(%v)/%v?charset=utf8&parseTime=True&loc=UTC&time_zone=%%27UTC%%27", Configs.DbUser, Configs.DbPass, host, Configs.DbData) conn = fmt.Sprintf("%v:%v@tcp(%v)/%v?charset=utf8&parseTime=True&loc=UTC&time_zone=%%27UTC%%27", CoreApp.Config.DbUser, CoreApp.Config.DbPass, host, CoreApp.Config.DbData)
case "postgres": case "postgres":
sslMode := "disable" sslMode := "disable"
if postgresSSL != "" { if postgresSSL != "" {
sslMode = postgresSSL sslMode = postgresSSL
} }
conn = fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v timezone=UTC sslmode=%v", Configs.DbHost, Configs.DbPort, Configs.DbUser, Configs.DbData, Configs.DbPass, sslMode) conn = fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v timezone=UTC sslmode=%v", CoreApp.Config.DbHost, CoreApp.Config.DbPort, CoreApp.Config.DbUser, CoreApp.Config.DbData, CoreApp.Config.DbPass, sslMode)
case "mssql": case "mssql":
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort) host := fmt.Sprintf("%v:%v", CoreApp.Config.DbHost, CoreApp.Config.DbPort)
conn = fmt.Sprintf("sqlserver://%v:%v@%v?database=%v", Configs.DbUser, Configs.DbPass, host, Configs.DbData) conn = fmt.Sprintf("sqlserver://%v:%v@%v?database=%v", CoreApp.Config.DbUser, CoreApp.Config.DbPass, host, CoreApp.Config.DbData)
} }
log.WithFields(utils.ToFields(c, conn)).Debugln("attempting to connect to database")
dbSession, err := gorm.Open(dbType, conn) dbSession, err := gorm.Open(dbType, conn)
if err != nil { if err != nil {
log.Debugln(fmt.Sprintf("Database connection error %v", err))
if retry { if retry {
log.Infoln(fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", Configs.DbHost)) log.Errorln(fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", CoreApp.Config.DbHost))
return db.waitForDb() return c.waitForDb()
} else { } else {
return err return err
} }
} }
log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database")
if dbType == "sqlite3" { if dbType == "sqlite3" {
dbSession.DB().SetMaxOpenConns(1) dbSession.DB().SetMaxOpenConns(1)
} }
@ -259,9 +262,9 @@ func (db *DbConfig) Connect(retry bool, location string) error {
} }
// waitForDb will sleep for 5 seconds and try to connect to the database again // waitForDb will sleep for 5 seconds and try to connect to the database again
func (db *DbConfig) waitForDb() error { func (c *Core) waitForDb() error {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
return db.Connect(true, utils.Directory) return c.Connect(true, utils.Directory)
} }
// DatabaseMaintence will automatically delete old records from 'failures' and 'hits' // DatabaseMaintence will automatically delete old records from 'failures' and 'hits'
@ -285,14 +288,14 @@ func DeleteAllSince(table string, date time.Time) {
} }
// Update will save the config.yml file // Update will save the config.yml file
func (db *DbConfig) Update() error { func (c *Core) UpdateConfig() error {
var err error var err error
config, err := os.Create(utils.Directory + "/config.yml") config, err := os.Create(utils.Directory + "/config.yml")
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return err return err
} }
data, err := yaml.Marshal(db) data, err := yaml.Marshal(c.Config)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return err return err
@ -303,30 +306,33 @@ func (db *DbConfig) Update() error {
} }
// Save will initially create the config.yml file // Save will initially create the config.yml file
func (db *DbConfig) Save() (*DbConfig, error) { func (c *Core) SaveConfig(configs *types.DbConfig) (*types.DbConfig, error) {
config, err := os.Create(utils.Directory + "/config.yml") config, err := os.Create(utils.Directory + "/config.yml")
defer config.Close()
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return nil, err return nil, err
} }
db.ApiKey = utils.NewSHA1Hash(16) defer config.Close()
db.ApiSecret = utils.NewSHA1Hash(16) log.WithFields(utils.ToFields(configs)).Debugln("saving config file at: " + utils.Directory + "/config.yml")
data, err := yaml.Marshal(db) c.Config = configs
c.Config.ApiKey = utils.NewSHA1Hash(16)
c.Config.ApiSecret = utils.NewSHA1Hash(16)
data, err := yaml.Marshal(configs)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
return nil, err return nil, err
} }
config.WriteString(string(data)) config.WriteString(string(data))
return db, err log.WithFields(utils.ToFields(configs)).Infoln("saved config file at: " + utils.Directory + "/config.yml")
return c.Config, err
} }
// CreateCore will initialize the global variable 'CoreApp". This global variable contains most of Statping app. // CreateCore will initialize the global variable 'CoreApp". This global variable contains most of Statping app.
func (c *DbConfig) CreateCore() *Core { func (c *Core) CreateCore() *Core {
newCore := &types.Core{ newCore := &types.Core{
Name: c.Project, Name: c.Name,
Description: c.Description, Description: c.Description,
Config: "config.yml", ConfigFile: utils.Directory + "/config.yml",
ApiKey: c.ApiKey, ApiKey: c.ApiKey,
ApiSecret: c.ApiSecret, ApiSecret: c.ApiSecret,
Domain: c.Domain, Domain: c.Domain,
@ -344,7 +350,7 @@ func (c *DbConfig) CreateCore() *Core {
} }
// DropDatabase will DROP each table Statping created // DropDatabase will DROP each table Statping created
func (db *DbConfig) DropDatabase() error { func (c *Core) DropDatabase() error {
log.Infoln("Dropping Database Tables...") log.Infoln("Dropping Database Tables...")
err := DbSession.DropTableIfExists("checkins") err := DbSession.DropTableIfExists("checkins")
err = DbSession.DropTableIfExists("checkin_hits") err = DbSession.DropTableIfExists("checkin_hits")
@ -361,7 +367,7 @@ func (db *DbConfig) DropDatabase() error {
} }
// CreateDatabase will CREATE TABLES for each of the Statping elements // CreateDatabase will CREATE TABLES for each of the Statping elements
func (db *DbConfig) CreateDatabase() error { func (c *Core) CreateDatabase() error {
var err error var err error
log.Infoln("Creating Database Tables...") log.Infoln("Creating Database Tables...")
for _, table := range DbModels { for _, table := range DbModels {
@ -379,7 +385,7 @@ func (db *DbConfig) CreateDatabase() error {
// MigrateDatabase will migrate the database structure to current version. // MigrateDatabase will migrate the database structure to current version.
// This function will NOT remove previous records, tables or columns from the database. // This function will NOT remove previous records, tables or columns from the database.
// If this function has an issue, it will ROLLBACK to the previous state. // If this function has an issue, it will ROLLBACK to the previous state.
func (db *DbConfig) MigrateDatabase() error { func (c *Core) MigrateDatabase() error {
log.Infoln("Migrating Database Tables...") log.Infoln("Migrating Database Tables...")
tx := DbSession.Begin() tx := DbSession.Begin()
defer func() { defer func() {

View File

@ -506,18 +506,18 @@ func TmpRecords(dbFile string) error {
var err error var err error
CoreApp = NewCore() CoreApp = NewCore()
CoreApp.Name = "Tester" CoreApp.Name = "Tester"
Configs = &DbConfig{ configs := &types.DbConfig{
DbConn: "sqlite", DbConn: "sqlite",
Project: "Tester", Project: "Tester",
Location: utils.Directory, Location: utils.Directory,
SqlFile: sqlFile, SqlFile: sqlFile,
} }
log.Infoln("saving config.yml in: " + utils.Directory) log.Infoln("saving config.yml in: " + utils.Directory)
if Configs, err = Configs.Save(); err != nil { if configs, err = CoreApp.SaveConfig(configs); err != nil {
return err return err
} }
log.Infoln("loading config.yml from: " + utils.Directory) log.Infoln("loading config.yml from: " + utils.Directory)
if Configs, err = LoadConfigFile(utils.Directory); err != nil { if configs, err = LoadConfigFile(utils.Directory); err != nil {
return err return err
} }
log.Infoln("connecting to database") log.Infoln("connecting to database")
@ -533,7 +533,7 @@ func TmpRecords(dbFile string) error {
} }
log.Infoln("loading config.yml from: " + utils.Directory) log.Infoln("loading config.yml from: " + utils.Directory)
if err := Configs.Connect(false, utils.Directory); err != nil { if err := CoreApp.Connect(false, utils.Directory); err != nil {
return err return err
} }
log.Infoln("selecting the Core variable") log.Infoln("selecting the Core variable")
@ -557,15 +557,15 @@ func TmpRecords(dbFile string) error {
log.Infoln(tmpSqlFile + " not found, creating a new database...") log.Infoln(tmpSqlFile + " not found, creating a new database...")
if err := Configs.Connect(false, utils.Directory); err != nil { if err := CoreApp.Connect(false, utils.Directory); err != nil {
return err return err
} }
log.Infoln("creating database") log.Infoln("creating database")
if err := Configs.CreateDatabase(); err != nil { if err := CoreApp.CreateDatabase(); err != nil {
return err return err
} }
log.Infoln("migrating database") log.Infoln("migrating database")
if err := Configs.MigrateDatabase(); err != nil { if err := CoreApp.MigrateDatabase(); err != nil {
return err return err
} }
log.Infoln("insert large sample data into database") log.Infoln("insert large sample data into database")

View File

@ -240,7 +240,7 @@ func Dbtimestamp(group string, column string) string {
default: default:
seconds = 60 seconds = 60
} }
switch CoreApp.DbConnection { switch CoreApp.Config.DbConn {
case "mysql": case "mysql":
return fmt.Sprintf("CONCAT(date_format(created_at, '%%Y-%%m-%%d %%H:00:00')) AS timeframe, AVG(%v) AS value", column) return fmt.Sprintf("CONCAT(date_format(created_at, '%%Y-%%m-%%d %%H:00:00')) AS timeframe, AVG(%v) AS value", column)
case "postgres": case "postgres":
@ -281,7 +281,7 @@ func GraphDataRaw(service types.ServiceInterface, start, end time.Time, group st
var createdTime time.Time var createdTime time.Time
var err error var err error
rows.Scan(&createdAt, &value) rows.Scan(&createdAt, &value)
if CoreApp.DbConnection == "postgres" { if CoreApp.Config.DbConn == "postgres" {
createdTime, err = time.Parse(types.TIME_NANO, createdAt) createdTime, err = time.Parse(types.TIME_NANO, createdAt)
if err != nil { if err != nil {
log.Errorln(fmt.Errorf("issue parsing time from database: %v to %v", createdAt, types.TIME_NANO)) log.Errorln(fmt.Errorf("issue parsing time from database: %v to %v", createdAt, types.TIME_NANO))

View File

@ -350,13 +350,13 @@ func TestSelectServiceLink(t *testing.T) {
} }
func TestDbtimestamp(t *testing.T) { func TestDbtimestamp(t *testing.T) {
CoreApp.DbConnection = "mysql" CoreApp.Config.DbConn = "mysql"
query := Dbtimestamp("minute", "latency") query := Dbtimestamp("minute", "latency")
assert.Equal(t, "CONCAT(date_format(created_at, '%Y-%m-%d %H:00:00')) AS timeframe, AVG(latency) AS value", query) assert.Equal(t, "CONCAT(date_format(created_at, '%Y-%m-%d %H:00:00')) AS timeframe, AVG(latency) AS value", query)
CoreApp.DbConnection = "postgres" CoreApp.Config.DbConn = "postgres"
query = Dbtimestamp("minute", "latency") query = Dbtimestamp("minute", "latency")
assert.Equal(t, "date_trunc('minute', created_at) AS timeframe, AVG(latency) AS value", query) assert.Equal(t, "date_trunc('minute', created_at) AS timeframe, AVG(latency) AS value", query)
CoreApp.DbConnection = "sqlite" CoreApp.Config.DbConn = "sqlite"
query = Dbtimestamp("minute", "latency") query = Dbtimestamp("minute", "latency")
assert.Equal(t, "datetime((strftime('%s', created_at) / 60) * 60, 'unixepoch') AS timeframe, AVG(latency) as value", query) assert.Equal(t, "datetime((strftime('%s', created_at) / 60) * 60, 'unixepoch') AS timeframe, AVG(latency) as value", query)
} }

View File

@ -104,6 +104,9 @@ func RunHTTPServer(ip string, port int) error {
// IsReadAuthenticated will allow Read Only authentication for some routes // IsReadAuthenticated will allow Read Only authentication for some routes
func IsReadAuthenticated(r *http.Request) bool { func IsReadAuthenticated(r *http.Request) bool {
if core.SetupMode {
return false
}
var token string var token string
query := r.URL.Query() query := r.URL.Query()
key := query.Get("api") key := query.Get("api")
@ -130,6 +133,9 @@ func IsFullAuthenticated(r *http.Request) bool {
if core.CoreApp == nil { if core.CoreApp == nil {
return true return true
} }
if core.SetupMode {
return false
}
if sessionStore == nil { if sessionStore == nil {
return true return true
} }
@ -147,6 +153,9 @@ func IsFullAuthenticated(r *http.Request) bool {
// IsAdmin returns true if the user session is an administrator // IsAdmin returns true if the user session is an administrator
func IsAdmin(r *http.Request) bool { func IsAdmin(r *http.Request) bool {
if core.SetupMode {
return false
}
session, err := sessionStore.Get(r, cookieKey) session, err := sessionStore.Get(r, cookieKey)
if err != nil { if err != nil {
return false return false
@ -159,6 +168,9 @@ func IsAdmin(r *http.Request) bool {
// IsUser returns true if the user is registered // IsUser returns true if the user is registered
func IsUser(r *http.Request) bool { func IsUser(r *http.Request) bool {
if core.SetupMode {
return false
}
if os.Getenv("GO_ENV") == "test" { if os.Getenv("GO_ENV") == "test" {
return true return true
} }

View File

@ -21,7 +21,7 @@ import (
) )
func indexHandler(w http.ResponseWriter, r *http.Request) { func indexHandler(w http.ResponseWriter, r *http.Request) {
if core.Configs == nil { if core.CoreApp.Config == nil {
http.Redirect(w, r, "/setup", http.StatusSeeOther) http.Redirect(w, r, "/setup", http.StatusSeeOther)
return return
} }
@ -32,7 +32,7 @@ func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
health := map[string]interface{}{ health := map[string]interface{}{
"services": len(core.Services()), "services": len(core.Services()),
"online": true, "online": true,
"setup": core.Configs != nil, "setup": core.CoreApp.Config != nil,
} }
returnJson(health, w, r) returnJson(health, w, r)
} }

View File

@ -15,6 +15,9 @@ func sendLog(handler func(w http.ResponseWriter, r *http.Request)) http.Handler
t1 := utils.Now() t1 := utils.Now()
handler(w, r) handler(w, r)
t2 := utils.Now().Sub(t1) t2 := utils.Now().Sub(t1)
if r.RequestURI == "/logs/line" {
return
}
log.WithFields(utils.ToFields(w, r)). log.WithFields(utils.ToFields(w, r)).
WithField("url", r.RequestURI). WithField("url", r.RequestURI).
WithField("method", r.Method). WithField("method", r.Method).
@ -59,7 +62,7 @@ func cached(duration, contentType string, handler func(w http.ResponseWriter, r
content := CacheStorage.Get(r.RequestURI) content := CacheStorage.Get(r.RequestURI)
w.Header().Set("Content-Type", contentType) w.Header().Set("Content-Type", contentType)
w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Origin", "*")
if core.Configs == nil { if core.CoreApp.Config == nil {
handler(w, r) handler(w, r)
return return
} }

View File

@ -38,7 +38,7 @@ func Router() *mux.Router {
dir := utils.Directory dir := utils.Directory
CacheStorage = NewStorage() CacheStorage = NewStorage()
r := mux.NewRouter() r := mux.NewRouter()
r.Handle("/", http.HandlerFunc(indexHandler)) r.Handle("/", sendLog(indexHandler))
if source.UsingAssets(dir) { if source.UsingAssets(dir) {
indexHandler := http.FileServer(http.Dir(dir + "/assets/")) indexHandler := http.FileServer(http.Dir(dir + "/assets/"))
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(dir+"/assets/css")))) r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(dir+"/assets/css"))))
@ -55,9 +55,9 @@ func Router() *mux.Router {
r.PathPrefix("/favicon.ico").Handler(http.FileServer(source.TmplBox.HTTPBox())) r.PathPrefix("/favicon.ico").Handler(http.FileServer(source.TmplBox.HTTPBox()))
r.PathPrefix("/banner.png").Handler(http.FileServer(source.TmplBox.HTTPBox())) r.PathPrefix("/banner.png").Handler(http.FileServer(source.TmplBox.HTTPBox()))
} }
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler)) r.Handle("/charts.js", sendLog(renderServiceChartsHandler))
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET") r.Handle("/setup", sendLog(setupHandler)).Methods("GET")
r.Handle("/setup", http.HandlerFunc(processSetupHandler)).Methods("POST") r.Handle("/setup", sendLog(processSetupHandler)).Methods("POST")
r.Handle("/dashboard", sendLog(dashboardHandler)).Methods("GET") r.Handle("/dashboard", sendLog(dashboardHandler)).Methods("GET")
r.Handle("/dashboard", sendLog(loginHandler)).Methods("POST") r.Handle("/dashboard", sendLog(loginHandler)).Methods("POST")
r.Handle("/logout", sendLog(logoutHandler)) r.Handle("/logout", sendLog(logoutHandler))

View File

@ -39,7 +39,7 @@ func setupHandler(w http.ResponseWriter, r *http.Request) {
func processSetupHandler(w http.ResponseWriter, r *http.Request) { func processSetupHandler(w http.ResponseWriter, r *http.Request) {
var err error var err error
if core.Services() != nil { if !core.SetupMode {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -57,10 +57,9 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
domain := r.PostForm.Get("domain") domain := r.PostForm.Get("domain")
email := r.PostForm.Get("email") email := r.PostForm.Get("email")
sample := r.PostForm.Get("sample_data") == "on" sample := r.PostForm.Get("sample_data") == "on"
log.Warnln(sample)
dir := utils.Directory dir := utils.Directory
config := &core.DbConfig{ config := &types.DbConfig{
DbConn: dbConn, DbConn: dbConn,
DbHost: dbHost, DbHost: dbHost,
DbUser: dbUser, DbUser: dbUser,
@ -77,21 +76,23 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
Location: utils.Directory, Location: utils.Directory,
} }
if core.Configs, err = config.Save(); err != nil { log.WithFields(utils.ToFields(core.CoreApp, config)).Debugln("new configs posted")
if _, err := core.CoreApp.SaveConfig(config); err != nil {
log.Errorln(err) log.Errorln(err)
config.Error = err config.Error = err
setupResponseError(w, r, config) setupResponseError(w, r, config)
return return
} }
if core.Configs, err = core.LoadConfigFile(dir); err != nil { if _, err = core.LoadConfigFile(dir); err != nil {
log.Errorln(err) log.Errorln(err)
config.Error = err config.Error = err
setupResponseError(w, r, config) setupResponseError(w, r, config)
return return
} }
if err = core.Configs.Connect(false, dir); err != nil { if err = core.CoreApp.Connect(false, dir); err != nil {
log.Errorln(err) log.Errorln(err)
core.DeleteConfig() core.DeleteConfig()
config.Error = err config.Error = err
@ -99,10 +100,10 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
config.DropDatabase() core.CoreApp.DropDatabase()
config.CreateDatabase() core.CoreApp.CreateDatabase()
core.CoreApp, err = config.InsertCore() core.CoreApp, err = core.CoreApp.InsertCore(config)
if err != nil { if err != nil {
log.Errorln(err) log.Errorln(err)
config.Error = err config.Error = err

View File

@ -4,6 +4,15 @@
{{template "nav"}} {{template "nav"}}
<div class="col-12"> <div class="col-12">
{{if eq (len CoreApp.Services) 0}}
<div class="jumbotron jumbotron-fluid">
<div class="text-center">
<h1 class="display-4">No Services!</h1>
<a class="lead">You don't have any websites or applications being monitored by your Statping server. <p><a href="/service/create" class="btn btn-secondary mt-3">Add Service</a></p></p>
</div>
</div>
{{end}}
{{if ne (len .Services) 0}} {{if ne (len .Services) 0}}
<h1 class="text-black-50">Services <a href="/service/create" class="btn btn-outline-success mt-1 float-right"> <h1 class="text-black-50">Services <a href="/service/create" class="btn btn-outline-success mt-1 float-right">
<i class="fas fa-plus"></i> Create</a> <i class="fas fa-plus"></i> Create</a>

View File

@ -31,7 +31,7 @@ type AllNotifiers interface{}
type Core struct { type Core struct {
Name string `gorm:"not null;column:name" json:"name"` Name string `gorm:"not null;column:name" json:"name"`
Description string `gorm:"not null;column:description" json:"description,omitempty"` Description string `gorm:"not null;column:description" json:"description,omitempty"`
Config string `gorm:"column:config" json:"-"` ConfigFile string `gorm:"column:config" json:"-"`
ApiKey string `gorm:"column:api_key" json:"-"` ApiKey string `gorm:"column:api_key" json:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"` ApiSecret string `gorm:"column:api_secret" json:"-"`
Style string `gorm:"not null;column:style" json:"style,omitempty"` Style string `gorm:"not null;column:style" json:"style,omitempty"`
@ -44,11 +44,11 @@ type Core struct {
Timezone float32 `gorm:"column:timezone;default:-8.0" json:"timezone,omitempty"` Timezone float32 `gorm:"column:timezone;default:-8.0" json:"timezone,omitempty"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"` UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
DbConnection string `gorm:"-" json:"database"`
Started time.Time `gorm:"-" json:"started_on"` Started time.Time `gorm:"-" json:"started_on"`
Services []ServiceInterface `gorm:"-" json:"-"` Services []ServiceInterface `gorm:"-" json:"-"`
Plugins []*Info `gorm:"-" json:"-"` Plugins []*Info `gorm:"-" json:"-"`
Repos []PluginJSON `gorm:"-" json:"-"` Repos []PluginJSON `gorm:"-" json:"-"`
AllPlugins []PluginActions `gorm:"-" json:"-"` AllPlugins []PluginActions `gorm:"-" json:"-"`
Notifications []AllNotifiers `gorm:"-" json:"-"` Notifications []AllNotifiers `gorm:"-" json:"-"`
Config *DbConfig `gorm:"-" json:"-"`
} }

View File

@ -115,8 +115,7 @@ func createLog(dir string) error {
// InitLogs will create the '/logs' directory and creates a file '/logs/statup.log' for application logging // InitLogs will create the '/logs' directory and creates a file '/logs/statup.log' for application logging
func InitLogs() error { func InitLogs() error {
err := createLog(Directory) if err := createLog(Directory); err != nil {
if err != nil {
return err return err
} }
ljLogger = &lumberjack.Logger{ ljLogger = &lumberjack.Logger{
@ -135,12 +134,13 @@ func InitLogs() error {
checkVerboseMode() checkVerboseMode()
LastLines = make([]*logRow, 0) LastLines = make([]*logRow, 0)
return err return nil
} }
// checkVerboseMode will reset the Logging verbose setting // checkVerboseMode will reset the Logging verbose setting. You can set
// the verbose level with "-v 3" or by setting VERBOSE=3 environment variable.
// statping -v 1 (only Warnings) // statping -v 1 (only Warnings)
// statping -v 2 (Info and Warnings) // statping -v 2 (Info and Warnings, default)
// statping -v 3 (Info, Warnings and Debug) // statping -v 3 (Info, Warnings and Debug)
// statping -v 4 (Info, Warnings, Debug and Traces (SQL queries)) // statping -v 4 (Info, Warnings, Debug and Traces (SQL queries))
func checkVerboseMode() { func checkVerboseMode() {
@ -157,6 +157,7 @@ func checkVerboseMode() {
default: default:
Log.SetLevel(Logger.InfoLevel) Log.SetLevel(Logger.InfoLevel)
} }
Log.Debugf("logging running in %v mode", Log.GetLevel().String())
} }
// CloseLogs will close the log file correctly on shutdown // CloseLogs will close the log file correctly on shutdown

View File

@ -61,6 +61,7 @@ func init() {
Log.Out = ioutil.Discard Log.Out = ioutil.Discard
return return
} }
Log.Debugln("current working directory: ", Directory)
Log.AddHook(new(hook)) Log.AddHook(new(hook))
Log.SetNoLock() Log.SetNoLock()
checkVerboseMode() checkVerboseMode()
@ -174,6 +175,7 @@ func UnderScoreString(str string) string {
// exists := FileExists("assets/css/base.css") // exists := FileExists("assets/css/base.css")
func FileExists(name string) bool { func FileExists(name string) bool {
if _, err := os.Stat(name); err != nil { if _, err := os.Stat(name); err != nil {
Log.Debugf("file exist: %v (%v)", name, !os.IsNotExist(err))
if os.IsNotExist(err) { if os.IsNotExist(err) {
return false return false
} }