Improving command line interface (#4689)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
dcf11a14d8
Коммит
026553e4f8
277
cmd/platform/server.go
Обычный файл
277
cmd/platform/server.go
Обычный файл
@@ -0,0 +1,277 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
l4g "github.com/alecthomas/log4go"
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/einterfaces"
|
||||
"github.com/mattermost/platform/manualtesting"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/mattermost/platform/web"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Run the Mattermost server",
|
||||
RunE: runServerCmd,
|
||||
}
|
||||
|
||||
func runServerCmd(cmd *cobra.Command, args []string) error {
|
||||
config, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runServer(config)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runServer(configFileLocation string) {
|
||||
if errstr := doLoadConfig(configFileLocation); errstr != "" {
|
||||
l4g.Exit("Unable to load mattermost configuration file: ", errstr)
|
||||
return
|
||||
}
|
||||
|
||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||
utils.TestConnection(utils.Cfg)
|
||||
|
||||
pwd, _ := os.Getwd()
|
||||
l4g.Info(utils.T("mattermost.current_version"), model.CurrentVersion, model.BuildNumber, model.BuildDate, model.BuildHash, model.BuildHashEnterprise)
|
||||
l4g.Info(utils.T("mattermost.entreprise_enabled"), model.BuildEnterpriseReady)
|
||||
l4g.Info(utils.T("mattermost.working_dir"), pwd)
|
||||
l4g.Info(utils.T("mattermost.config_file"), utils.FindConfigFile(configFileLocation))
|
||||
|
||||
// Enable developer settings if this is a "dev" build
|
||||
if model.BuildNumber == "dev" {
|
||||
*utils.Cfg.ServiceSettings.EnableDeveloper = true
|
||||
}
|
||||
|
||||
cmdUpdateDb30()
|
||||
|
||||
api.NewServer()
|
||||
api.InitStores()
|
||||
api.InitRouter()
|
||||
api.InitApi()
|
||||
web.InitWeb()
|
||||
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
api.LoadLicense()
|
||||
}
|
||||
|
||||
if !utils.IsLicensed && len(utils.Cfg.SqlSettings.DataSourceReplicas) > 1 {
|
||||
l4g.Critical(utils.T("store.sql.read_replicas_not_licensed.critical"))
|
||||
return
|
||||
}
|
||||
|
||||
resetStatuses()
|
||||
|
||||
api.StartServer()
|
||||
|
||||
// If we allow testing then listen for manual testing URL hits
|
||||
if utils.Cfg.ServiceSettings.EnableTesting {
|
||||
manualtesting.InitManualTesting()
|
||||
}
|
||||
|
||||
setDiagnosticId()
|
||||
go runSecurityAndDiagnosticsJob()
|
||||
|
||||
if complianceI := einterfaces.GetComplianceInterface(); complianceI != nil {
|
||||
complianceI.StartComplianceDailyJob()
|
||||
}
|
||||
|
||||
if einterfaces.GetClusterInterface() != nil {
|
||||
einterfaces.GetClusterInterface().StartInterNodeCommunication()
|
||||
}
|
||||
|
||||
if einterfaces.GetMetricsInterface() != nil {
|
||||
einterfaces.GetMetricsInterface().StartServer()
|
||||
}
|
||||
|
||||
// wait for kill signal before attempting to gracefully shutdown
|
||||
// the running service
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-c
|
||||
|
||||
if einterfaces.GetClusterInterface() != nil {
|
||||
einterfaces.GetClusterInterface().StopInterNodeCommunication()
|
||||
}
|
||||
|
||||
if einterfaces.GetMetricsInterface() != nil {
|
||||
einterfaces.GetMetricsInterface().StopServer()
|
||||
}
|
||||
|
||||
api.StopServer()
|
||||
}
|
||||
|
||||
func runSecurityAndDiagnosticsJob() {
|
||||
doSecurityAndDiagnostics()
|
||||
model.CreateRecurringTask("Security and Diagnostics", doSecurityAndDiagnostics, time.Hour*4)
|
||||
}
|
||||
|
||||
func resetStatuses() {
|
||||
if result := <-api.Srv.Store.Status().ResetAll(); result.Err != nil {
|
||||
l4g.Error(utils.T("mattermost.reset_status.error"), result.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func setDiagnosticId() {
|
||||
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
|
||||
props := result.Data.(model.StringMap)
|
||||
|
||||
id := props[model.SYSTEM_DIAGNOSTIC_ID]
|
||||
if len(id) == 0 {
|
||||
id = model.NewId()
|
||||
systemId := &model.System{Name: model.SYSTEM_DIAGNOSTIC_ID, Value: id}
|
||||
<-api.Srv.Store.System().Save(systemId)
|
||||
}
|
||||
|
||||
utils.CfgDiagnosticId = id
|
||||
}
|
||||
}
|
||||
|
||||
func doSecurityAndDiagnostics() {
|
||||
if *utils.Cfg.ServiceSettings.EnableSecurityFixAlert {
|
||||
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
|
||||
props := result.Data.(model.StringMap)
|
||||
lastSecurityTime, _ := strconv.ParseInt(props[model.SYSTEM_LAST_SECURITY_TIME], 10, 0)
|
||||
currentTime := model.GetMillis()
|
||||
|
||||
if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
|
||||
l4g.Debug(utils.T("mattermost.security_checks.debug"))
|
||||
|
||||
v := url.Values{}
|
||||
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ID, utils.CfgDiagnosticId)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ENTERPRISE_READY, model.BuildEnterpriseReady)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_CATEGORY, utils.VAL_DIAGNOSTIC_CATEGORY_DEFAULT)
|
||||
|
||||
if len(props[model.SYSTEM_RAN_UNIT_TESTS]) > 0 {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_UNIT_TESTS, "1")
|
||||
} else {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_UNIT_TESTS, "0")
|
||||
}
|
||||
|
||||
systemSecurityLastTime := &model.System{Name: model.SYSTEM_LAST_SECURITY_TIME, Value: strconv.FormatInt(currentTime, 10)}
|
||||
if lastSecurityTime == 0 {
|
||||
<-api.Srv.Store.System().Save(systemSecurityLastTime)
|
||||
} else {
|
||||
<-api.Srv.Store.System().Update(systemSecurityLastTime)
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_TEAM_COUNT, strconv.FormatInt(tcr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
res, err := http.Get(utils.DIAGNOSTIC_URL + "/security?" + v.Encode())
|
||||
if err != nil {
|
||||
l4g.Error(utils.T("mattermost.security_info.error"))
|
||||
return
|
||||
}
|
||||
|
||||
bulletins := model.SecurityBulletinsFromJson(res.Body)
|
||||
ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
|
||||
for _, bulletin := range bulletins {
|
||||
if bulletin.AppliesToVersion == model.CurrentVersion {
|
||||
if props["SecurityBulletin_"+bulletin.Id] == "" {
|
||||
if results := <-api.Srv.Store.User().GetSystemAdminProfiles(); results.Err != nil {
|
||||
l4g.Error(utils.T("mattermost.system_admins.error"))
|
||||
return
|
||||
} else {
|
||||
users := results.Data.(map[string]*model.User)
|
||||
|
||||
resBody, err := http.Get(utils.DIAGNOSTIC_URL + "/bulletins/" + bulletin.Id)
|
||||
if err != nil {
|
||||
l4g.Error(utils.T("mattermost.security_bulletin.error"))
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resBody.Body)
|
||||
res.Body.Close()
|
||||
if err != nil || resBody.StatusCode != 200 {
|
||||
l4g.Error(utils.T("mattermost.security_bulletin_read.error"))
|
||||
return
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
l4g.Info(utils.T("mattermost.send_bulletin.info"), bulletin.Id, user.Email)
|
||||
utils.SendMail(user.Email, utils.T("mattermost.bulletin.subject"), string(body))
|
||||
}
|
||||
}
|
||||
|
||||
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
|
||||
<-api.Srv.Store.System().Save(bulletinSeen)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if *utils.Cfg.LogSettings.EnableDiagnostics {
|
||||
utils.SendGeneralDiagnostics()
|
||||
sendServerDiagnostics()
|
||||
}
|
||||
}
|
||||
|
||||
func sendServerDiagnostics() {
|
||||
var userCount int64
|
||||
var activeUserCount int64
|
||||
var teamCount int64
|
||||
|
||||
if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
|
||||
userCount = ucr.Data.(int64)
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
|
||||
activeUserCount = ucr.Data.(int64)
|
||||
}
|
||||
|
||||
if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
|
||||
teamCount = tcr.Data.(int64)
|
||||
}
|
||||
|
||||
utils.SendDiagnostic(utils.TRACK_ACTIVITY, map[string]interface{}{
|
||||
"registered_users": userCount,
|
||||
"active_users": activeUserCount,
|
||||
"teams": teamCount,
|
||||
})
|
||||
|
||||
edition := model.BuildEnterpriseReady
|
||||
version := model.CurrentVersion
|
||||
database := utils.Cfg.SqlSettings.DriverName
|
||||
operatingSystem := runtime.GOOS
|
||||
|
||||
utils.SendDiagnostic(utils.TRACK_VERSION, map[string]interface{}{
|
||||
"edition": edition,
|
||||
"version": version,
|
||||
"database": database,
|
||||
"operating_system": operatingSystem,
|
||||
})
|
||||
}
|
||||
Ссылка в новой задаче
Block a user