mirror of https://github.com/statping/statping
				
				
				
			remove API_KEY (unused code), just use API_SECRET, YAML unmarshal, services.yml services auto creation
							parent
							
								
									2893218ed6
								
							
						
					
					
						commit
						d9e3cabb4e
					
				|  | @ -116,7 +116,7 @@ jobs: | |||
|           VERSION: ${{ env.VERSION }} | ||||
|           DB_CONN: sqlite3 | ||||
|           STATPING_DIR: ${{ github.workspace }} | ||||
|           API_KEY: demopassword123 | ||||
|           API_SECRET: demopassword123 | ||||
|           DISABLE_LOGS: true | ||||
|           ALLOW_REPORTS: true | ||||
|           PUSH_REQUEST: true | ||||
|  | @ -164,21 +164,3 @@ jobs: | |||
|           environment: ./dev/postman_environment.json | ||||
|           timeoutRequest: 15000 | ||||
|           delayRequest: 1000 | ||||
| 
 | ||||
|   pr-slack-update: | ||||
|     needs: [pr-test, pr-test-postman] | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout Statping Repo | ||||
|         uses: actions/checkout@v2 | ||||
| 
 | ||||
|       - name: Setting ENV's | ||||
|         run: echo ::set-env name=VERSION::$(cat version.txt) | ||||
|         shell: bash | ||||
| 
 | ||||
|       - name: Slack Notification | ||||
|         uses: rtCamp/action-slack-notify@v2.0.0 | ||||
|         env: | ||||
|           SLACK_WEBHOOK: ${{ secrets.SLACK_URL }} | ||||
|           SLACK_CHANNEL: pull-requests | ||||
|           SLACK_USERNAME: StatpingDev | ||||
|  |  | |||
|  | @ -113,7 +113,7 @@ jobs: | |||
|           VERSION: ${{ env.VERSION }} | ||||
|           DB_CONN: sqlite3 | ||||
|           STATPING_DIR: ${{ github.workspace }} | ||||
|           API_KEY: demopassword123 | ||||
|           API_SECRET: demopassword123 | ||||
|           DISABLE_LOGS: true | ||||
|           ALLOW_REPORTS: true | ||||
|           COVERALLS: ${{ secrets.COVERALLS }} | ||||
|  |  | |||
|  | @ -36,3 +36,4 @@ docker | |||
| tmp | ||||
| /frontend/cypress/screenshots/ | ||||
| /frontend/cypress/videos/ | ||||
| services.yml | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| # Upcoming | ||||
| - Added missing information to Mail notification ([#472](https://github.com/statping/statping/issues/472)) | ||||
| - Added service.yml file to auto create services (https://github.com/statping/statping/wiki/services.yml) | ||||
| - Removed Core API_KEY, (unused code, use API_SECRET) | ||||
| 
 | ||||
| # 0.90.33 (04-24-2020) | ||||
| - Fixed config loading method | ||||
|  |  | |||
|  | @ -153,16 +153,12 @@ func sigterm() { | |||
| 
 | ||||
| // mainProcess will initialize the Statping application and run the HTTP server
 | ||||
| func mainProcess() error { | ||||
| 	if err := services.ServicesFromEnvFile(); err != nil { | ||||
| 		errStr := "error 'SERVICE' environment variable" | ||||
| 		log.Errorln(errStr) | ||||
| 		return errors.Wrap(err, errStr) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := InitApp(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	services.LoadServicesYaml() | ||||
| 
 | ||||
| 	if err := handlers.RunHTTPServer(ipAddress, port); err != nil { | ||||
| 		log.Fatalln(err) | ||||
| 		return errors.Wrap(err, "http server") | ||||
|  |  | |||
|  | @ -27,7 +27,6 @@ services: | |||
| #      VIRTUAL_PORT: 8888 | ||||
| #      GO_ENV: test | ||||
| #      DB_CONN: sqlite | ||||
| #      API_KEY: exampleapikey | ||||
| #      API_SECRET: exampleapisecret | ||||
| #      NAME: Statping on SQLite | ||||
| #      DOMAIN: http://localhost:4000 | ||||
|  | @ -59,7 +58,6 @@ services: | |||
|       VIRTUAL_HOST: sqlite.dev.statping.com | ||||
|       VIRTUAL_PORT: 8080 | ||||
|       DB_CONN: sqlite | ||||
|       API_KEY: exampleapikey | ||||
|       API_SECRET: exampleapisecret | ||||
|       NAME: Statping on SQLite | ||||
|       DOMAIN: http://localhost:4000 | ||||
|  | @ -96,7 +94,6 @@ services: | |||
|       DB_DATABASE: statping | ||||
|       DB_USER: root | ||||
|       DB_PASS: password123 | ||||
|       API_KEY: exampleapikey | ||||
|       API_SECRET: exampleapisecret | ||||
|       NAME: Statping on MySQL | ||||
|       DOMAIN: http://localhost:4005 | ||||
|  | @ -134,7 +131,6 @@ services: | |||
|       DB_DATABASE: statping | ||||
|       DB_USER: root | ||||
|       DB_PASS: password123 | ||||
|       API_KEY: exampleapikey | ||||
|       API_SECRET: exampleapisecret | ||||
|       NAME: Statping on Postgres | ||||
|       DOMAIN: http://localhost:4010 | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ services: | |||
|       - ./utils:/go/src/github.com/statping/statping/utils/ | ||||
|     environment: | ||||
|       DB_CONN: sqlite | ||||
|       API_KEY: exampleapikey | ||||
|       API_SECRET: exampleapisecret | ||||
|       NAME: Statping | ||||
|       DOMAIN: http://localhost:8585 | ||||
|  |  | |||
|  | @ -7,14 +7,43 @@ services: | |||
|     image: statping/statping | ||||
|     ports: | ||||
|       - 8080:8080 | ||||
|     networks: | ||||
|       - backend | ||||
|     volumes: | ||||
|       - /root/statping:/app | ||||
|     environment: | ||||
|       PORT: 8080 | ||||
|       SERVICES: '[{"name": "Local Statping", "type": "http", "domain": "http://localhost:8585", "interval": 30}]' | ||||
|       DB_CONN: sqlite | ||||
|       API_KEY: exampleapikey | ||||
|       API_SECRET: exampleapisecret | ||||
|       NAME: Statping on SQLite | ||||
|       DOMAIN: http://localhost:8080 | ||||
|       DESCRIPTION: This is a dev environment on SQLite! | ||||
|       ADMIN_USER: admin | ||||
|       ADMIN_PASS: admin | ||||
| 
 | ||||
|   postgres: | ||||
|     hostname: postgres | ||||
|     image: postgres | ||||
|     environment: | ||||
|       POSTGRES_PASSWORD: password123 | ||||
|       POSTGRES_DB: statping | ||||
|       POSTGRES_USER: root | ||||
|     networks: | ||||
|       - backend | ||||
|     volumes: | ||||
|       - /root/postgres:/var/lib/postgresql/data | ||||
| 
 | ||||
|   mysql: | ||||
|     hostname: mysql | ||||
|     image: mysql:5.7 | ||||
|     environment: | ||||
|       MYSQL_ROOT_PASSWORD: password123 | ||||
|       MYSQL_DATABASE: statping | ||||
|       MYSQL_USER: root | ||||
|       MYSQL_PASSWORD: password123 | ||||
|     networks: | ||||
|       - backend | ||||
|     volumes: | ||||
|       - /root/mysql:/var/lib/mysql | ||||
| 
 | ||||
| networks: | ||||
|   backend: | ||||
|  |  | |||
|  | @ -30,7 +30,6 @@ context('Notifier Tests', () => { | |||
|     cy.visit('/dashboard/settings') | ||||
|     cy.get('#notifiers_tabs > a').should('have.length', 10) | ||||
| 
 | ||||
|     cy.get('#api_key').should('not.have.value', '') | ||||
|     cy.get('#api_secret').should('not.have.value', '') | ||||
|   }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ context('Settings Tests', () => { | |||
|     cy.visit('/dashboard/settings') | ||||
|     cy.get('#notifiers_tabs > a').should('have.length', 10) | ||||
| 
 | ||||
|     cy.get('#api_key').should('not.have.value', '') | ||||
|     cy.get('#api_secret').should('not.have.value', '') | ||||
|   }) | ||||
| 
 | ||||
|  | @ -50,7 +49,6 @@ context('Settings Tests', () => { | |||
|     cy.get('#description').should('have.value', 'Statping can use Cypress e2e testing to make it more stable!') | ||||
|     cy.get('#domain').should('have.value', 'http://localhost:8888') | ||||
|     cy.get('#footer').should('have.value', 'Statping Custom Footer') | ||||
|     cy.get('#api_key').should('not.have.value', '') | ||||
|     cy.get('#api_secret').should('not.have.value', '') | ||||
|   }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,19 +67,6 @@ | |||
|                         <div class="card text-black-50 bg-white mt-3"> | ||||
|                             <div class="card-header">API Settings</div> | ||||
|                             <div class="card-body"> | ||||
|                                 <div class="form-group row"> | ||||
|                                     <label class="col-sm-3 col-form-label">API Key</label> | ||||
|                                     <div class="col-sm-9"> | ||||
|                                         <div class="input-group"> | ||||
|                                         <input v-model="core.api_key" type="text" class="form-control" id="api_key" readonly> | ||||
|                                             <div class="input-group-append copy-btn"> | ||||
|                                                 <button @click.prevent="copy(core.api_key)" class="btn btn-outline-secondary" type="button">Copy</button> | ||||
|                                             </div> | ||||
|                                         </div> | ||||
|                                         <small class="form-text text-muted">API Key can be used for read only routes</small> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
| 
 | ||||
|                                 <div class="form-group row"> | ||||
|                                     <label class="col-sm-3 col-form-label">API Secret</label> | ||||
|                                     <div class="col-sm-9"> | ||||
|  |  | |||
|  | @ -80,6 +80,7 @@ func Router() *mux.Router { | |||
| 	api.Handle("/api/clear_cache", authenticated(apiClearCacheHandler, false)) | ||||
| 	api.Handle("/api/core", authenticated(apiCoreHandler, false)).Methods("POST") | ||||
| 	api.Handle("/api/oauth", scoped(apiOAuthHandler)).Methods("GET") | ||||
| 	api.Handle("/api/oauth/{provider}", http.HandlerFunc(oauthHandler)) | ||||
| 	api.Handle("/api/logs", authenticated(logsHandler, false)).Methods("GET") | ||||
| 	api.Handle("/api/logs/last", authenticated(logsLineHandler, false)).Methods("GET") | ||||
| 
 | ||||
|  |  | |||
|  | @ -78,7 +78,6 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) { | |||
| 	c := &core.Core{ | ||||
| 		Name:        project, | ||||
| 		Description: description, | ||||
| 		ApiKey:      utils.Params.GetString("API_KEY"), | ||||
| 		ApiSecret:   utils.Params.GetString("API_SECRET"), | ||||
| 		Domain:      domain, | ||||
| 		Version:     core.App.Version, | ||||
|  |  | |||
|  | @ -40,9 +40,7 @@ func Connect(configs *DbConfig, retry bool) error { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	apiKey := p.GetString("API_KEY") | ||||
| 	apiSecret := p.GetString("API_SECRET") | ||||
| 	configs.ApiKey = apiKey | ||||
| 	configs.ApiSecret = apiSecret | ||||
| 
 | ||||
| 	log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database") | ||||
|  |  | |||
|  | @ -46,9 +46,6 @@ func LoadConfigFile(directory string) (*DbConfig, error) { | |||
| 	if db.Location != "" { | ||||
| 		p.Set("LOCATION", db.Location) | ||||
| 	} | ||||
| 	if db.ApiKey != "" { | ||||
| 		p.Set("API_KEY", db.ApiKey) | ||||
| 	} | ||||
| 	if db.ApiSecret != "" { | ||||
| 		p.Set("API_SECRET", db.ApiSecret) | ||||
| 	} | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ type DbConfig struct { | |||
| 	DbPass      string `yaml:"password" json:"-"` | ||||
| 	DbData      string `yaml:"database" json:"-"` | ||||
| 	DbPort      int    `yaml:"port" json:"-"` | ||||
| 	ApiKey      string `yaml:"api_key" json:"-"` | ||||
| 	ApiSecret   string `yaml:"api_secret" json:"-"` | ||||
| 	Project     string `yaml:"-" json:"-"` | ||||
| 	Description string `yaml:"-" json:"-"` | ||||
|  |  | |||
|  | @ -23,7 +23,6 @@ type Core struct { | |||
| 	Name          string          `gorm:"not null;column:name" json:"name,omitempty"` | ||||
| 	Description   string          `gorm:"not null;column:description" json:"description,omitempty"` | ||||
| 	ConfigFile    string          `gorm:"column:config" json:"-"` | ||||
| 	ApiKey        string          `gorm:"column:api_key" json:"api_key" scope:"admin"` | ||||
| 	ApiSecret     string          `gorm:"column:api_secret" json:"api_secret" scope:"admin"` | ||||
| 	Style         string          `gorm:"not null;column:style" json:"style,omitempty"` | ||||
| 	Footer        null.NullString `gorm:"column:footer" json:"footer"` | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| package null | ||||
| 
 | ||||
| import "encoding/json" | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
| // MarshalJSON for NullInt64
 | ||||
| func (i NullInt64) MarshalJSON() ([]byte, error) { | ||||
|  | @ -33,3 +36,35 @@ func (s NullString) MarshalJSON() ([]byte, error) { | |||
| 	} | ||||
| 	return json.Marshal(s.String) | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON for NullInt64
 | ||||
| func (i NullInt64) MarshalYAML() (interface{}, error) { | ||||
| 	if !i.Valid { | ||||
| 		return 0, nil | ||||
| 	} | ||||
| 	return yaml.Marshal(i.Int64) | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON for NullFloat64
 | ||||
| func (f NullFloat64) MarshalYAML() (interface{}, error) { | ||||
| 	if !f.Valid { | ||||
| 		return 0.0, nil | ||||
| 	} | ||||
| 	return yaml.Marshal(f.Float64) | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON for NullBool
 | ||||
| func (bb NullBool) MarshalYAML() (interface{}, error) { | ||||
| 	if !bb.Valid { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return yaml.Marshal(bb.Bool) | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON for NullString
 | ||||
| func (s NullString) MarshalYAML() (interface{}, error) { | ||||
| 	if !s.Valid { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	return yaml.Marshal(s.String) | ||||
| } | ||||
|  |  | |||
|  | @ -29,3 +29,43 @@ func (s *NullString) UnmarshalJSON(b []byte) error { | |||
| 	s.Valid = (err == nil) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // UnmarshalYAML for NullInt64
 | ||||
| func (i *NullInt64) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var val int64 | ||||
| 	if err := unmarshal(&val); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*i = NewNullInt64(val) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalYAML for NullFloat64
 | ||||
| func (f *NullFloat64) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var val float64 | ||||
| 	if err := unmarshal(&val); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*f = NewNullFloat64(val) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalYAML for NullBool
 | ||||
| func (bb *NullBool) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var val bool | ||||
| 	if err := unmarshal(&val); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*bb = NewNullBool(val) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalYAML for NullFloat64
 | ||||
| func (s *NullString) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||
| 	var val string | ||||
| 	if err := unmarshal(&val); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*s = NewNullString(val) | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -1,59 +0,0 @@ | |||
| package services | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/statping/statping/utils" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| // findServiceByHas will return a service that matches the SHA256 hash of a service
 | ||||
| // Service hash example: sha256(name:EXAMPLEdomain:HTTP://DOMAIN.COMport:8080type:HTTPmethod:GET)
 | ||||
| func findServiceByHash(hash string) *Service { | ||||
| 	for _, service := range All() { | ||||
| 		if service.Hash() == hash { | ||||
| 			return service | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func ServicesFromEnvFile() error { | ||||
| 	servicesEnv := utils.Params.GetString("SERVICES_FILE") | ||||
| 	if servicesEnv == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	file, err := os.Open(servicesEnv) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "error opening 'SERVICES_FILE' at: %s", servicesEnv) | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 
 | ||||
| 	var serviceLines []string | ||||
| 	scanner := bufio.NewScanner(file) | ||||
| 	for scanner.Scan() { | ||||
| 		serviceLines = append(serviceLines, scanner.Text()) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(serviceLines) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	for k, service := range serviceLines { | ||||
| 
 | ||||
| 		svr, err := ValidateService(service) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "invalid service at index %d in SERVICES_FILE environment variable", k) | ||||
| 		} | ||||
| 		if findServiceByHash(svr.Hash()) == nil { | ||||
| 			if err := svr.Create(); err != nil { | ||||
| 				return errors.Wrapf(err, "could not create service %s", svr.Name) | ||||
| 			} | ||||
| 			log.Infof("Created new service '%s'", svr.Name) | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | @ -8,12 +8,9 @@ import ( | |||
| 	"github.com/statping/statping/types" | ||||
| 	"github.com/statping/statping/types/failures" | ||||
| 	"github.com/statping/statping/types/hits" | ||||
| 	"github.com/statping/statping/types/null" | ||||
| 	"github.com/statping/statping/utils" | ||||
| 	"net/url" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
|  | @ -233,57 +230,6 @@ func SelectAllServices(start bool) (map[int64]*Service, error) { | |||
| 	return allServices, nil | ||||
| } | ||||
| 
 | ||||
| func ValidateService(line string) (*Service, error) { | ||||
| 	p, err := url.Parse(line) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	newService := new(Service) | ||||
| 
 | ||||
| 	domain := p.Host | ||||
| 	newService.Name = niceDomainName(domain, p.Path) | ||||
| 	if p.Port() != "" { | ||||
| 		newService.Port = int(utils.ToInt(p.Port())) | ||||
| 		if p.Scheme != "http" && p.Scheme != "https" { | ||||
| 			domain = strings.ReplaceAll(domain, ":"+p.Port(), "") | ||||
| 		} | ||||
| 	} | ||||
| 	newService.Domain = domain | ||||
| 
 | ||||
| 	switch p.Scheme { | ||||
| 	case "http", "https": | ||||
| 		newService.Type = "http" | ||||
| 		newService.Method = "get" | ||||
| 		if p.Scheme == "https" { | ||||
| 			newService.VerifySSL = null.NewNullBool(true) | ||||
| 		} | ||||
| 	default: | ||||
| 		newService.Type = p.Scheme | ||||
| 	} | ||||
| 	return newService, nil | ||||
| } | ||||
| 
 | ||||
| func niceDomainName(domain string, paths string) string { | ||||
| 	domain = strings.ReplaceAll(domain, "www.", "") | ||||
| 	splitPath := strings.Split(paths, "/") | ||||
| 	if len(splitPath) == 1 { | ||||
| 		return domain | ||||
| 	} | ||||
| 	var addedName []string | ||||
| 	for k, p := range splitPath { | ||||
| 		if k > 2 { | ||||
| 			break | ||||
| 		} | ||||
| 		if len(p) > 16 { | ||||
| 			addedName = append(addedName, p+"...") | ||||
| 			break | ||||
| 		} else { | ||||
| 			addedName = append(addedName, p) | ||||
| 		} | ||||
| 	} | ||||
| 	return domain + strings.Join(addedName, "/") | ||||
| } | ||||
| 
 | ||||
| func (s *Service) UpdateStats() *Service { | ||||
| 	s.Online24Hours = s.OnlineDaysPercent(1) | ||||
| 	s.Online7Days = s.OnlineDaysPercent(7) | ||||
|  |  | |||
|  | @ -22,56 +22,56 @@ func Services() map[int64]*Service { | |||
| 
 | ||||
| // Service is the main struct for Services
 | ||||
| type Service struct { | ||||
| 	Id                  int64               `gorm:"primary_key;column:id" json:"id"` | ||||
| 	Name                string              `gorm:"column:name" json:"name"` | ||||
| 	Domain              string              `gorm:"column:domain" json:"domain" private:"true" scope:"user,admin"` | ||||
| 	Expected            null.NullString     `gorm:"column:expected" json:"expected" scope:"user,admin"` | ||||
| 	ExpectedStatus      int                 `gorm:"default:200;column:expected_status" json:"expected_status" scope:"user,admin"` | ||||
| 	Interval            int                 `gorm:"default:30;column:check_interval" json:"check_interval"` | ||||
| 	Type                string              `gorm:"column:check_type" json:"type" scope:"user,admin"` | ||||
| 	Method              string              `gorm:"column:method" json:"method" scope:"user,admin"` | ||||
| 	PostData            null.NullString     `gorm:"column:post_data" json:"post_data" scope:"user,admin"` | ||||
| 	Port                int                 `gorm:"not null;column:port" json:"port" scope:"user,admin"` | ||||
| 	Timeout             int                 `gorm:"default:30;column:timeout" json:"timeout" scope:"user,admin"` | ||||
| 	Order               int                 `gorm:"default:0;column:order_id" json:"order_id"` | ||||
| 	VerifySSL           null.NullBool       `gorm:"default:false;column:verify_ssl" json:"verify_ssl" scope:"user,admin"` | ||||
| 	Public              null.NullBool       `gorm:"default:true;column:public" json:"public"` | ||||
| 	GroupId             int                 `gorm:"default:0;column:group_id" json:"group_id"` | ||||
| 	Headers             null.NullString     `gorm:"column:headers" json:"headers" scope:"user,admin"` | ||||
| 	Permalink           null.NullString     `gorm:"column:permalink" json:"permalink"` | ||||
| 	Redirect            null.NullBool       `gorm:"default:false;column:redirect" json:"redirect" scope:"user,admin"` | ||||
| 	CreatedAt           time.Time           `gorm:"column:created_at" json:"created_at"` | ||||
| 	UpdatedAt           time.Time           `gorm:"column:updated_at" json:"updated_at"` | ||||
| 	Online              bool                `gorm:"-" json:"online"` | ||||
| 	Latency             int64               `gorm:"-" json:"latency"` | ||||
| 	PingTime            int64               `gorm:"-" json:"ping_time"` | ||||
| 	Online24Hours       float32             `gorm:"-" json:"online_24_hours"` | ||||
| 	Online7Days         float32             `gorm:"-" json:"online_7_days"` | ||||
| 	AvgResponse         int64               `gorm:"-" json:"avg_response"` | ||||
| 	FailuresLast24Hours int                 `gorm:"-" json:"failures_24_hours"` | ||||
| 	Running             chan bool           `gorm:"-" json:"-"` | ||||
| 	Checkpoint          time.Time           `gorm:"-" json:"-"` | ||||
| 	SleepDuration       time.Duration       `gorm:"-" json:"-"` | ||||
| 	LastResponse        string              `gorm:"-" json:"-"` | ||||
| 	NotifyAfter         int64               `gorm:"column:notify_after" json:"notify_after" scope:"user,admin"` | ||||
| 	notifyAfterCount    int64               `gorm:"-" json:"-"` | ||||
| 	AllowNotifications  null.NullBool       `gorm:"default:true;column:allow_notifications" json:"allow_notifications" scope:"user,admin"` | ||||
| 	UserNotified        bool                `gorm:"-" json:"-"`                                                                          // True if the User was already notified about a Downtime
 | ||||
| 	UpdateNotify        null.NullBool       `gorm:"default:true;column:notify_all_changes" json:"notify_all_changes" scope:"user,admin"` // This Variable is a simple copy of `core.CoreApp.UpdateNotify.Bool`
 | ||||
| 	DownText            string              `gorm:"-" json:"-"`                                                                          // Contains the current generated Downtime Text
 | ||||
| 	SuccessNotified     bool                `gorm:"-" json:"-"`                                                                          // Is 'true' if the user has already be informed that the Services now again available
 | ||||
| 	LastStatusCode      int                 `gorm:"-" json:"status_code"` | ||||
| 	Failures            []*failures.Failure `gorm:"-" json:"failures,omitempty" scope:"user,admin"` | ||||
| 	AllCheckins         []*checkins.Checkin `gorm:"-" json:"checkins,omitempty" scope:"user,admin"` | ||||
| 	LastLookupTime      int64               `gorm:"-" json:"-"` | ||||
| 	LastLatency         int64               `gorm:"-" json:"-"` | ||||
| 	LastCheck           time.Time           `gorm:"-" json:"-"` | ||||
| 	LastOnline          time.Time           `gorm:"-" json:"last_success"` | ||||
| 	LastOffline         time.Time           `gorm:"-" json:"last_error"` | ||||
| 	Stats               *Stats              `gorm:"-" json:"stats,omitempty"` | ||||
| 	Id                  int64               `gorm:"primary_key;column:id" json:"id" yaml:"id"` | ||||
| 	Name                string              `gorm:"column:name" json:"name" yaml:"name"` | ||||
| 	Domain              string              `gorm:"column:domain" json:"domain" yaml:"domain" private:"true" scope:"user,admin"` | ||||
| 	Expected            null.NullString     `gorm:"column:expected" json:"expected" yaml:"expected" scope:"user,admin"` | ||||
| 	ExpectedStatus      int                 `gorm:"default:200;column:expected_status" json:"expected_status" yaml:"expected_status" scope:"user,admin"` | ||||
| 	Interval            int                 `gorm:"default:30;column:check_interval" json:"check_interval" yaml:"check_interval"` | ||||
| 	Type                string              `gorm:"column:check_type" json:"type" scope:"user,admin" yaml:"type"` | ||||
| 	Method              string              `gorm:"column:method" json:"method" scope:"user,admin" yaml:"method"` | ||||
| 	PostData            null.NullString     `gorm:"column:post_data" json:"post_data" scope:"user,admin" yaml:"post_data"` | ||||
| 	Port                int                 `gorm:"not null;column:port" json:"port" scope:"user,admin" yaml:"port"` | ||||
| 	Timeout             int                 `gorm:"default:30;column:timeout" json:"timeout" scope:"user,admin" yaml:"timeout"` | ||||
| 	Order               int                 `gorm:"default:0;column:order_id" json:"order_id" yaml:"order_id"` | ||||
| 	VerifySSL           null.NullBool       `gorm:"default:false;column:verify_ssl" json:"verify_ssl" scope:"user,admin" yaml:"verify_ssl"` | ||||
| 	Public              null.NullBool       `gorm:"default:true;column:public" json:"public" yaml:"public"` | ||||
| 	GroupId             int                 `gorm:"default:0;column:group_id" json:"group_id" yaml:"group_id"` | ||||
| 	Headers             null.NullString     `gorm:"column:headers" json:"headers" scope:"user,admin" yaml:"headers"` | ||||
| 	Permalink           null.NullString     `gorm:"column:permalink" json:"permalink" yaml:"permalink"` | ||||
| 	Redirect            null.NullBool       `gorm:"default:false;column:redirect" json:"redirect" scope:"user,admin" yaml:"redirect"` | ||||
| 	CreatedAt           time.Time           `gorm:"column:created_at" json:"created_at" yaml:"-"` | ||||
| 	UpdatedAt           time.Time           `gorm:"column:updated_at" json:"updated_at" yaml:"-"` | ||||
| 	Online              bool                `gorm:"-" json:"online" yaml:"-"` | ||||
| 	Latency             int64               `gorm:"-" json:"latency" yaml:"-"` | ||||
| 	PingTime            int64               `gorm:"-" json:"ping_time" yaml:"-"` | ||||
| 	Online24Hours       float32             `gorm:"-" json:"online_24_hours" yaml:"-"` | ||||
| 	Online7Days         float32             `gorm:"-" json:"online_7_days" yaml:"-"` | ||||
| 	AvgResponse         int64               `gorm:"-" json:"avg_response" yaml:"-"` | ||||
| 	FailuresLast24Hours int                 `gorm:"-" json:"failures_24_hours" yaml:"-"` | ||||
| 	Running             chan bool           `gorm:"-" json:"-" yaml:"-"` | ||||
| 	Checkpoint          time.Time           `gorm:"-" json:"-" yaml:"-"` | ||||
| 	SleepDuration       time.Duration       `gorm:"-" json:"-" yaml:"-"` | ||||
| 	LastResponse        string              `gorm:"-" json:"-" yaml:"-"` | ||||
| 	NotifyAfter         int64               `gorm:"column:notify_after" json:"notify_after" yaml:"notify_after" scope:"user,admin"` | ||||
| 	notifyAfterCount    int64               `gorm:"-" json:"-" yaml:"-"` | ||||
| 	AllowNotifications  null.NullBool       `gorm:"default:true;column:allow_notifications" json:"allow_notifications" yaml:"allow_notifications" scope:"user,admin"` | ||||
| 	UserNotified        bool                `gorm:"-" json:"-" yaml:"-"`                                                                                           // True if the User was already notified about a Downtime
 | ||||
| 	UpdateNotify        null.NullBool       `gorm:"default:true;column:notify_all_changes" json:"notify_all_changes" yaml:"notify_all_changes" scope:"user,admin"` // This Variable is a simple copy of `core.CoreApp.UpdateNotify.Bool`
 | ||||
| 	DownText            string              `gorm:"-" json:"-" yaml:"-"`                                                                                           // Contains the current generated Downtime Text
 | ||||
| 	SuccessNotified     bool                `gorm:"-" json:"-" yaml:"-"`                                                                                           // Is 'true' if the user has already be informed that the Services now again available
 | ||||
| 	LastStatusCode      int                 `gorm:"-" json:"status_code" yaml:"-"` | ||||
| 	Failures            []*failures.Failure `gorm:"-" json:"failures,omitempty" yaml:"-" scope:"user,admin"` | ||||
| 	AllCheckins         []*checkins.Checkin `gorm:"-" json:"checkins,omitempty" yaml:"-" scope:"user,admin"` | ||||
| 	LastLookupTime      int64               `gorm:"-" json:"-" yaml:"-"` | ||||
| 	LastLatency         int64               `gorm:"-" json:"-" yaml:"-"` | ||||
| 	LastCheck           time.Time           `gorm:"-" json:"-" yaml:"-"` | ||||
| 	LastOnline          time.Time           `gorm:"-" json:"last_success" yaml:"-"` | ||||
| 	LastOffline         time.Time           `gorm:"-" json:"last_error" yaml:"-"` | ||||
| 	Stats               *Stats              `gorm:"-" json:"stats,omitempty" yaml:"-"` | ||||
| 
 | ||||
| 	SecondsOnline  int64 `gorm:"-" json:"-"` | ||||
| 	SecondsOffline int64 `gorm:"-" json:"-"` | ||||
| 	SecondsOnline  int64 `gorm:"-" json:"-" yaml:"-"` | ||||
| 	SecondsOffline int64 `gorm:"-" json:"-" yaml:"-"` | ||||
| } | ||||
| 
 | ||||
| type Stats struct { | ||||
|  |  | |||
|  | @ -0,0 +1,47 @@ | |||
| package services | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/statping/statping/utils" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
| type ServicesYaml struct { | ||||
| 	Services []Service `yaml:"services,flow"` | ||||
| } | ||||
| 
 | ||||
| // LoadServicesYaml will attempt to load the 'services.yml' file for Service Auto Creation on startup.
 | ||||
| func LoadServicesYaml() (*ServicesYaml, error) { | ||||
| 	f, err := utils.OpenFile("services.yml") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var svrs *ServicesYaml | ||||
| 	if err := yaml.Unmarshal([]byte(f), &svrs); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, svr := range svrs.Services { | ||||
| 		if findServiceByHash(svr.Hash()) == nil { | ||||
| 			if err := svr.Create(); err != nil { | ||||
| 				return nil, errors.Wrapf(err, "could not create service %s", svr.Name) | ||||
| 			} | ||||
| 			log.Infof("Automatically created service '%s' checking %s", svr.Name, svr.Domain) | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return svrs, nil | ||||
| } | ||||
| 
 | ||||
| // findServiceByHas will return a service that matches the SHA256 hash of a service
 | ||||
| // Service hash example: sha256(name:EXAMPLEdomain:HTTP://DOMAIN.COMport:8080type:HTTPmethod:GET)
 | ||||
| func findServiceByHash(hash string) *Service { | ||||
| 	for _, service := range All() { | ||||
| 		if service.Hash() == hash { | ||||
| 			return service | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 hunterlong
						hunterlong