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)"
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)" } } } }'
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
PATH:=/usr/local/bin:$(GOPATH)/bin:$(PATH)

View File

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

View File

@ -39,6 +39,7 @@ var (
envFile string
verboseMode int
port int
log = utils.Log.WithField("type", "cmd")
)
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(&envFile, "env", "", "IP address to run the Statping 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()
if os.Getenv("PORT") != "" {
@ -75,8 +76,7 @@ func main() {
source.Assets()
utils.VerboseMode = verboseMode
if err := utils.InitLogs(); err != nil {
fmt.Printf("Statping Log Error: \n %v\n", err)
os.Exit(2)
log.Fatalln("Statping Log Error: \n %v\n", err)
}
args := flag.Args()
@ -90,16 +90,18 @@ func main() {
os.Exit(1)
}
}
utils.Log.Info(fmt.Sprintf("Starting Statping v%v", VERSION))
log.Info(fmt.Sprintf("Starting Statping v%v", VERSION))
updateDisplay()
core.Configs, err = core.LoadConfigFile(utils.Directory)
configs, err := core.LoadConfigFile(utils.Directory)
if err != nil {
utils.Log.Errorln(err)
log.Errorln(err)
core.SetupMode = true
utils.Log.Infoln(handlers.RunHTTPServer(ipAddress, port))
os.Exit(1)
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
log.Fatalln(err)
}
}
core.CoreApp.Config = configs
mainProcess()
}
@ -122,7 +124,7 @@ func sigterm() {
func loadDotEnvs() error {
err := godotenv.Load(envFile)
if err == nil {
utils.Log.Infoln("Environment file '.env' Loaded")
log.Infoln("Environment file '.env' Loaded")
}
return err
}
@ -131,15 +133,16 @@ func loadDotEnvs() error {
func mainProcess() {
dir := utils.Directory
var err error
err = core.Configs.Connect(false, dir)
err = core.CoreApp.Connect(false, dir)
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()
if !core.SetupMode {
plugin.LoadPlugins()
fmt.Println(handlers.RunHTTPServer(ipAddress, port))
os.Exit(1)
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
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
func LoadConfigFile(directory string) (*DbConfig, error) {
var configs *DbConfig
func LoadConfigFile(directory string) (*types.DbConfig, error) {
var configs *types.DbConfig
if os.Getenv("DB_CONN") != "" {
log.Infoln("DB_CONN environment variable was found, waiting for database...")
return LoadUsingEnv()
}
log.Debugln("attempting to read config file at: " + directory + "/config.yml")
file, err := ioutil.ReadFile(directory + "/config.yml")
if err != nil {
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 {
return nil, err
}
Configs = configs
return Configs, err
log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + directory + "/config.yml")
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.
func LoadUsingEnv() (*DbConfig, error) {
func LoadUsingEnv() (*types.DbConfig, error) {
Configs, err := EnvToConfig()
if err != nil {
return Configs, err
@ -61,21 +63,20 @@ func LoadUsingEnv() (*DbConfig, error) {
} else {
CoreApp.Domain = os.Getenv("DOMAIN")
}
CoreApp.DbConnection = Configs.DbConn
CoreApp.UseCdn = types.NewNullBool(os.Getenv("USE_CDN") == "true")
err = Configs.Connect(true, utils.Directory)
err = CoreApp.Connect(true, utils.Directory)
if err != nil {
log.Errorln(err)
return nil, err
}
Configs.Save()
CoreApp.SaveConfig(Configs)
exists := DbSession.HasTable("core")
if !exists {
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
Configs.DropDatabase()
Configs.CreateDatabase()
CoreApp, err = Configs.InsertCore()
CoreApp.DropDatabase()
CoreApp.CreateDatabase()
CoreApp, err = CoreApp.InsertCore(Configs)
if err != nil {
log.Errorln(err)
}
@ -118,24 +119,23 @@ func DefaultPort(db string) int64 {
}
// EnvToConfig converts environment variables to a DbConfig variable
func EnvToConfig() (*DbConfig, error) {
Configs = new(DbConfig)
func EnvToConfig() (*types.DbConfig, error) {
var err error
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_HOST") == "" {
return Configs, errors.New("Missing DB_HOST environment variable")
return nil, errors.New("Missing DB_HOST environment variable")
}
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") == "" {
return Configs, errors.New("Missing DB_PASS environment variable")
return nil, errors.New("Missing DB_PASS environment variable")
}
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"))
@ -161,7 +161,7 @@ func EnvToConfig() (*DbConfig, error) {
adminPass = "admin"
}
Configs = &DbConfig{
configs := &types.DbConfig{
DbConn: os.Getenv("DB_CONN"),
DbHost: os.Getenv("DB_HOST"),
DbUser: os.Getenv("DB_USER"),
@ -178,7 +178,8 @@ func EnvToConfig() (*DbConfig, error) {
Location: utils.Directory,
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
@ -194,7 +195,8 @@ func SampleData() error {
// DeleteConfig will delete the 'config.yml' file
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 {
log.Errorln(err)
return err

View File

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

View File

@ -68,7 +68,7 @@ func TestLoadDbConfig(t *testing.T) {
}
func TestDbConnection(t *testing.T) {
err := Configs.Connect(false, dir)
err := CoreApp.Connect(false, dir)
assert.Nil(t, err)
}
@ -77,7 +77,7 @@ func TestDropDatabase(t *testing.T) {
if skipNewDb {
t.SkipNow()
}
err := Configs.DropDatabase()
err := CoreApp.DropDatabase()
assert.Nil(t, err)
}
@ -86,13 +86,13 @@ func TestSeedSchemaDatabase(t *testing.T) {
if skipNewDb {
t.SkipNow()
}
err := Configs.CreateDatabase()
err := CoreApp.CreateDatabase()
assert.Nil(t, err)
}
func TestMigrateDatabase(t *testing.T) {
t.SkipNow()
err := Configs.MigrateDatabase()
err := CoreApp.MigrateDatabase()
assert.Nil(t, err)
}
@ -103,9 +103,9 @@ func TestSeedDatabase(t *testing.T) {
}
func TestReLoadDbConfig(t *testing.T) {
err := Configs.Connect(false, dir)
err := CoreApp.Connect(false, dir)
assert.Nil(t, err)
assert.Equal(t, "sqlite", Configs.DbConn)
assert.Equal(t, "sqlite", CoreApp.Config.DbConn)
}
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
func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB {
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))
} 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))
@ -171,24 +171,24 @@ func (u *Message) AfterFind() (err error) {
}
// 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{
Name: db.Project,
Description: db.Description,
Config: "config.yml",
ConfigFile: "config.yml",
ApiKey: utils.NewSHA1Hash(9),
ApiSecret: utils.NewSHA1Hash(16),
Domain: db.Domain,
MigrationId: time.Now().Unix(),
Config: db,
}}
CoreApp.DbConnection = db.DbConn
query := coreDB().Create(&CoreApp)
return CoreApp, query.Error
}
func findDbFile() string {
if Configs.SqlFile != "" {
return Configs.SqlFile
if CoreApp.Config.SqlFile != "" {
return CoreApp.Config.SqlFile
}
filename := types.SqliteFilename
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
func (db *DbConfig) Connect(retry bool, location string) error {
func (c *Core) Connect(retry bool, location string) error {
postgresSSL := os.Getenv("POSTGRES_SSLMODE")
if DbSession != nil {
return nil
}
var conn, dbType string
var err error
dbType = Configs.DbConn
if Configs.DbPort == 0 {
Configs.DbPort = DefaultPort(dbType)
dbType = CoreApp.Config.DbConn
if CoreApp.Config.DbPort == 0 {
CoreApp.Config.DbPort = DefaultPort(dbType)
}
switch dbType {
case "sqlite":
@ -224,27 +224,30 @@ func (db *DbConfig) Connect(retry bool, location string) error {
conn = sqlFilename
dbType = "sqlite3"
case "mysql":
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.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)
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", CoreApp.Config.DbUser, CoreApp.Config.DbPass, host, CoreApp.Config.DbData)
case "postgres":
sslMode := "disable"
if 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":
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort)
conn = fmt.Sprintf("sqlserver://%v:%v@%v?database=%v", Configs.DbUser, Configs.DbPass, host, Configs.DbData)
host := fmt.Sprintf("%v:%v", CoreApp.Config.DbHost, CoreApp.Config.DbPort)
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)
if err != nil {
log.Debugln(fmt.Sprintf("Database connection error %v", err))
if retry {
log.Infoln(fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", Configs.DbHost))
return db.waitForDb()
log.Errorln(fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", CoreApp.Config.DbHost))
return c.waitForDb()
} else {
return err
}
}
log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database")
if dbType == "sqlite3" {
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
func (db *DbConfig) waitForDb() error {
func (c *Core) waitForDb() error {
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'
@ -285,14 +288,14 @@ func DeleteAllSince(table string, date time.Time) {
}
// Update will save the config.yml file
func (db *DbConfig) Update() error {
func (c *Core) UpdateConfig() error {
var err error
config, err := os.Create(utils.Directory + "/config.yml")
if err != nil {
log.Errorln(err)
return err
}
data, err := yaml.Marshal(db)
data, err := yaml.Marshal(c.Config)
if err != nil {
log.Errorln(err)
return err
@ -303,30 +306,33 @@ func (db *DbConfig) Update() error {
}
// 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")
defer config.Close()
if err != nil {
log.Errorln(err)
return nil, err
}
db.ApiKey = utils.NewSHA1Hash(16)
db.ApiSecret = utils.NewSHA1Hash(16)
data, err := yaml.Marshal(db)
defer config.Close()
log.WithFields(utils.ToFields(configs)).Debugln("saving config file at: " + utils.Directory + "/config.yml")
c.Config = configs
c.Config.ApiKey = utils.NewSHA1Hash(16)
c.Config.ApiSecret = utils.NewSHA1Hash(16)
data, err := yaml.Marshal(configs)
if err != nil {
log.Errorln(err)
return nil, err
}
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.
func (c *DbConfig) CreateCore() *Core {
func (c *Core) CreateCore() *Core {
newCore := &types.Core{
Name: c.Project,
Name: c.Name,
Description: c.Description,
Config: "config.yml",
ConfigFile: utils.Directory + "/config.yml",
ApiKey: c.ApiKey,
ApiSecret: c.ApiSecret,
Domain: c.Domain,
@ -344,7 +350,7 @@ func (c *DbConfig) CreateCore() *Core {
}
// DropDatabase will DROP each table Statping created
func (db *DbConfig) DropDatabase() error {
func (c *Core) DropDatabase() error {
log.Infoln("Dropping Database Tables...")
err := DbSession.DropTableIfExists("checkins")
err = DbSession.DropTableIfExists("checkin_hits")
@ -361,7 +367,7 @@ func (db *DbConfig) DropDatabase() error {
}
// CreateDatabase will CREATE TABLES for each of the Statping elements
func (db *DbConfig) CreateDatabase() error {
func (c *Core) CreateDatabase() error {
var err error
log.Infoln("Creating Database Tables...")
for _, table := range DbModels {
@ -379,7 +385,7 @@ func (db *DbConfig) CreateDatabase() error {
// MigrateDatabase will migrate the database structure to current version.
// 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.
func (db *DbConfig) MigrateDatabase() error {
func (c *Core) MigrateDatabase() error {
log.Infoln("Migrating Database Tables...")
tx := DbSession.Begin()
defer func() {

View File

@ -506,18 +506,18 @@ func TmpRecords(dbFile string) error {
var err error
CoreApp = NewCore()
CoreApp.Name = "Tester"
Configs = &DbConfig{
configs := &types.DbConfig{
DbConn: "sqlite",
Project: "Tester",
Location: utils.Directory,
SqlFile: sqlFile,
}
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
}
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
}
log.Infoln("connecting to database")
@ -533,7 +533,7 @@ func TmpRecords(dbFile string) error {
}
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
}
log.Infoln("selecting the Core variable")
@ -557,15 +557,15 @@ func TmpRecords(dbFile string) error {
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
}
log.Infoln("creating database")
if err := Configs.CreateDatabase(); err != nil {
if err := CoreApp.CreateDatabase(); err != nil {
return err
}
log.Infoln("migrating database")
if err := Configs.MigrateDatabase(); err != nil {
if err := CoreApp.MigrateDatabase(); err != nil {
return err
}
log.Infoln("insert large sample data into database")

View File

@ -240,7 +240,7 @@ func Dbtimestamp(group string, column string) string {
default:
seconds = 60
}
switch CoreApp.DbConnection {
switch CoreApp.Config.DbConn {
case "mysql":
return fmt.Sprintf("CONCAT(date_format(created_at, '%%Y-%%m-%%d %%H:00:00')) AS timeframe, AVG(%v) AS value", column)
case "postgres":
@ -281,7 +281,7 @@ func GraphDataRaw(service types.ServiceInterface, start, end time.Time, group st
var createdTime time.Time
var err error
rows.Scan(&createdAt, &value)
if CoreApp.DbConnection == "postgres" {
if CoreApp.Config.DbConn == "postgres" {
createdTime, err = time.Parse(types.TIME_NANO, createdAt)
if err != nil {
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) {
CoreApp.DbConnection = "mysql"
CoreApp.Config.DbConn = "mysql"
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)
CoreApp.DbConnection = "postgres"
CoreApp.Config.DbConn = "postgres"
query = Dbtimestamp("minute", "latency")
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")
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
func IsReadAuthenticated(r *http.Request) bool {
if core.SetupMode {
return false
}
var token string
query := r.URL.Query()
key := query.Get("api")
@ -130,6 +133,9 @@ func IsFullAuthenticated(r *http.Request) bool {
if core.CoreApp == nil {
return true
}
if core.SetupMode {
return false
}
if sessionStore == nil {
return true
}
@ -147,6 +153,9 @@ func IsFullAuthenticated(r *http.Request) bool {
// IsAdmin returns true if the user session is an administrator
func IsAdmin(r *http.Request) bool {
if core.SetupMode {
return false
}
session, err := sessionStore.Get(r, cookieKey)
if err != nil {
return false
@ -159,6 +168,9 @@ func IsAdmin(r *http.Request) bool {
// IsUser returns true if the user is registered
func IsUser(r *http.Request) bool {
if core.SetupMode {
return false
}
if os.Getenv("GO_ENV") == "test" {
return true
}

View File

@ -21,7 +21,7 @@ import (
)
func indexHandler(w http.ResponseWriter, r *http.Request) {
if core.Configs == nil {
if core.CoreApp.Config == nil {
http.Redirect(w, r, "/setup", http.StatusSeeOther)
return
}
@ -32,7 +32,7 @@ func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
health := map[string]interface{}{
"services": len(core.Services()),
"online": true,
"setup": core.Configs != nil,
"setup": core.CoreApp.Config != nil,
}
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()
handler(w, r)
t2 := utils.Now().Sub(t1)
if r.RequestURI == "/logs/line" {
return
}
log.WithFields(utils.ToFields(w, r)).
WithField("url", r.RequestURI).
WithField("method", r.Method).
@ -59,7 +62,7 @@ func cached(duration, contentType string, handler func(w http.ResponseWriter, r
content := CacheStorage.Get(r.RequestURI)
w.Header().Set("Content-Type", contentType)
w.Header().Set("Access-Control-Allow-Origin", "*")
if core.Configs == nil {
if core.CoreApp.Config == nil {
handler(w, r)
return
}

View File

@ -38,7 +38,7 @@ func Router() *mux.Router {
dir := utils.Directory
CacheStorage = NewStorage()
r := mux.NewRouter()
r.Handle("/", http.HandlerFunc(indexHandler))
r.Handle("/", sendLog(indexHandler))
if source.UsingAssets(dir) {
indexHandler := http.FileServer(http.Dir(dir + "/assets/"))
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("/banner.png").Handler(http.FileServer(source.TmplBox.HTTPBox()))
}
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler))
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET")
r.Handle("/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
r.Handle("/charts.js", sendLog(renderServiceChartsHandler))
r.Handle("/setup", sendLog(setupHandler)).Methods("GET")
r.Handle("/setup", sendLog(processSetupHandler)).Methods("POST")
r.Handle("/dashboard", sendLog(dashboardHandler)).Methods("GET")
r.Handle("/dashboard", sendLog(loginHandler)).Methods("POST")
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) {
var err error
if core.Services() != nil {
if !core.SetupMode {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
@ -57,10 +57,9 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
domain := r.PostForm.Get("domain")
email := r.PostForm.Get("email")
sample := r.PostForm.Get("sample_data") == "on"
log.Warnln(sample)
dir := utils.Directory
config := &core.DbConfig{
config := &types.DbConfig{
DbConn: dbConn,
DbHost: dbHost,
DbUser: dbUser,
@ -77,21 +76,23 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
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)
config.Error = err
setupResponseError(w, r, config)
return
}
if core.Configs, err = core.LoadConfigFile(dir); err != nil {
if _, err = core.LoadConfigFile(dir); err != nil {
log.Errorln(err)
config.Error = err
setupResponseError(w, r, config)
return
}
if err = core.Configs.Connect(false, dir); err != nil {
if err = core.CoreApp.Connect(false, dir); err != nil {
log.Errorln(err)
core.DeleteConfig()
config.Error = err
@ -99,10 +100,10 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
return
}
config.DropDatabase()
config.CreateDatabase()
core.CoreApp.DropDatabase()
core.CoreApp.CreateDatabase()
core.CoreApp, err = config.InsertCore()
core.CoreApp, err = core.CoreApp.InsertCore(config)
if err != nil {
log.Errorln(err)
config.Error = err

View File

@ -4,6 +4,15 @@
{{template "nav"}}
<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}}
<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>

View File

@ -31,7 +31,7 @@ type AllNotifiers interface{}
type Core struct {
Name string `gorm:"not null;column:name" json:"name"`
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:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"`
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"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
DbConnection string `gorm:"-" json:"database"`
Started time.Time `gorm:"-" json:"started_on"`
Services []ServiceInterface `gorm:"-" json:"-"`
Plugins []*Info `gorm:"-" json:"-"`
Repos []PluginJSON `gorm:"-" json:"-"`
AllPlugins []PluginActions `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
func InitLogs() error {
err := createLog(Directory)
if err != nil {
if err := createLog(Directory); err != nil {
return err
}
ljLogger = &lumberjack.Logger{
@ -135,12 +134,13 @@ func InitLogs() error {
checkVerboseMode()
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 2 (Info and Warnings)
// statping -v 2 (Info and Warnings, default)
// statping -v 3 (Info, Warnings and Debug)
// statping -v 4 (Info, Warnings, Debug and Traces (SQL queries))
func checkVerboseMode() {
@ -157,6 +157,7 @@ func checkVerboseMode() {
default:
Log.SetLevel(Logger.InfoLevel)
}
Log.Debugf("logging running in %v mode", Log.GetLevel().String())
}
// CloseLogs will close the log file correctly on shutdown

View File

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