[MM-31790] Support Packet Generation BACKEND (#16667)
* init commit * clean up the code * make mocks * fix translations * mocks and lint fixes * add tests * little fixes * Update i18n/en.json Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> * Update i18n/en.json Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> * Update i18n/en.json Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> * Update i18n/en.json Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> * Update i18n/en.json Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> * Address Comments * fix i18n * update api endpoint * add enable file and file level for conditional show of banner * Address Comments * Make it more clear about returns * Create zip file utility function * update en.json * address comments * write tests * check for data in test * remove warning string * Correct expected and actual * set database through environment variables * reset environment variable at end of test Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
Этот коммит содержится в:
185
app/server.go
185
app/server.go
@@ -6,8 +6,10 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash/maphash"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -23,6 +25,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
sentryhttp "github.com/getsentry/sentry-go/http"
|
||||
"github.com/gorilla/mux"
|
||||
@@ -636,6 +640,12 @@ func (s *Server) AppOptions() []AppOption {
|
||||
}
|
||||
}
|
||||
|
||||
// Return Database type (postgres or mysql) and current version of Mattermost
|
||||
func (s *Server) DatabaseTypeAndMattermostVersion() (string, string) {
|
||||
mattermostVersion, _ := s.Store.System().GetByName("Version")
|
||||
return *s.Config().SqlSettings.DriverName, mattermostVersion.Value
|
||||
}
|
||||
|
||||
// initLogging initializes and configures the logger. This may be called more than once.
|
||||
func (s *Server) initLogging() error {
|
||||
if s.Log == nil {
|
||||
@@ -1611,3 +1621,178 @@ func (s *Server) HttpService() httpservice.HTTPService {
|
||||
func (s *Server) SetLog(l *mlog.Logger) {
|
||||
s.Log = l
|
||||
}
|
||||
|
||||
func (a *App) GenerateSupportPacket() []model.FileData {
|
||||
// If any errors we come across within this function, we will log it in a warning.txt file so that we know why certain files did not get produced if any
|
||||
var warnings []string
|
||||
|
||||
// Creating an array of files that we are going to be adding to our zip file
|
||||
fileDatas := []model.FileData{}
|
||||
|
||||
// A array of the functions that we can iterate through since they all have the same return value
|
||||
functions := []func() (*model.FileData, string){
|
||||
a.generateSupportPacketYaml,
|
||||
a.createPluginsFile,
|
||||
a.createSanitizedConfigFile,
|
||||
a.getMattermostLog,
|
||||
a.getNotificationsLog,
|
||||
}
|
||||
|
||||
for _, fn := range functions {
|
||||
fileData, warning := fn()
|
||||
|
||||
if fileData != nil {
|
||||
fileDatas = append(fileDatas, *fileData)
|
||||
} else {
|
||||
warnings = append(warnings, warning)
|
||||
}
|
||||
}
|
||||
|
||||
// Adding a warning.txt file to the fileDatas if any warning
|
||||
if len(warnings) > 0 {
|
||||
finalWarning := strings.Join(warnings, "\n")
|
||||
fileDatas = append(fileDatas, model.FileData{
|
||||
Filename: "warning.txt",
|
||||
Body: []byte(finalWarning),
|
||||
})
|
||||
}
|
||||
|
||||
return fileDatas
|
||||
}
|
||||
|
||||
func (a *App) getNotificationsLog() (*model.FileData, string) {
|
||||
var warning string
|
||||
|
||||
// Getting notifications.log
|
||||
if *a.Srv().Config().NotificationLogSettings.EnableFile {
|
||||
// notifications.log
|
||||
notificationsLog := utils.GetNotificationsLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
|
||||
|
||||
notificationsLogFileData, notificationsLogFileDataErr := ioutil.ReadFile(notificationsLog)
|
||||
|
||||
if notificationsLogFileDataErr == nil {
|
||||
fileData := model.FileData{
|
||||
Filename: "notifications.log",
|
||||
Body: notificationsLogFileData,
|
||||
}
|
||||
return &fileData, ""
|
||||
}
|
||||
|
||||
warning = fmt.Sprintf("ioutil.ReadFile(notificationsLog) Error: %s", notificationsLogFileDataErr.Error())
|
||||
|
||||
} else {
|
||||
warning = "Unable to retrieve notifications.log because LogSettings: EnableFile is false in config.json"
|
||||
}
|
||||
|
||||
return nil, warning
|
||||
}
|
||||
|
||||
func (a *App) getMattermostLog() (*model.FileData, string) {
|
||||
var warning string
|
||||
|
||||
// Getting mattermost.log
|
||||
if *a.Srv().Config().LogSettings.EnableFile {
|
||||
// mattermost.log
|
||||
mattermostLog := utils.GetLogFileLocation(*a.Srv().Config().LogSettings.FileLocation)
|
||||
|
||||
mattermostLogFileData, mattermostLogFileDataErr := ioutil.ReadFile(mattermostLog)
|
||||
|
||||
if mattermostLogFileDataErr == nil {
|
||||
fileData := model.FileData{
|
||||
Filename: "mattermost.log",
|
||||
Body: mattermostLogFileData,
|
||||
}
|
||||
return &fileData, ""
|
||||
}
|
||||
warning = fmt.Sprintf("ioutil.ReadFile(mattermostLog) Error: %s", mattermostLogFileDataErr.Error())
|
||||
|
||||
} else {
|
||||
warning = "Unable to retrieve mattermost.log because LogSettings: EnableFile is false in config.json"
|
||||
}
|
||||
|
||||
return nil, warning
|
||||
}
|
||||
|
||||
func (a *App) createSanitizedConfigFile() (*model.FileData, string) {
|
||||
// Getting sanitized config, prettifying it, and then adding it to our file data array
|
||||
sanitizedConfigPrettyJSON, err := json.MarshalIndent(a.GetSanitizedConfig(), "", " ")
|
||||
if err == nil {
|
||||
fileData := model.FileData{
|
||||
Filename: "sanitized_config.json",
|
||||
Body: sanitizedConfigPrettyJSON,
|
||||
}
|
||||
return &fileData, ""
|
||||
}
|
||||
|
||||
warning := fmt.Sprintf("json.MarshalIndent(c.App.GetSanitizedConfig()) Error: %s", err.Error())
|
||||
return nil, warning
|
||||
}
|
||||
|
||||
func (a *App) createPluginsFile() (*model.FileData, string) {
|
||||
var warning string
|
||||
|
||||
// Getting the plugins installed on the server, prettify it, and then add them to the file data array
|
||||
pluginsResponse, appErr := a.GetPlugins()
|
||||
if appErr == nil {
|
||||
pluginsPrettyJSON, err := json.MarshalIndent(pluginsResponse, "", " ")
|
||||
if err == nil {
|
||||
fileData := model.FileData{
|
||||
Filename: "plugins.json",
|
||||
Body: pluginsPrettyJSON,
|
||||
}
|
||||
|
||||
return &fileData, ""
|
||||
}
|
||||
|
||||
warning = fmt.Sprintf("json.MarshalIndent(pluginsResponse) Error: %s", err.Error())
|
||||
} else {
|
||||
warning = fmt.Sprintf("c.App.GetPlugins() Error: %s", appErr.Error())
|
||||
}
|
||||
|
||||
return nil, warning
|
||||
}
|
||||
|
||||
func (a *App) generateSupportPacketYaml() (*model.FileData, string) {
|
||||
// Here we are getting information regarding Elastic Search
|
||||
var elasticServerVersion string
|
||||
var elasticServerPlugins []string
|
||||
if a.Srv().SearchEngine.ElasticsearchEngine != nil {
|
||||
elasticServerVersion = a.Srv().SearchEngine.ElasticsearchEngine.GetFullVersion()
|
||||
elasticServerPlugins = a.Srv().SearchEngine.ElasticsearchEngine.GetPlugins()
|
||||
}
|
||||
|
||||
// Here we are getting information regarding LDAP
|
||||
ldapInterface := a.Srv().Ldap
|
||||
var vendorName, vendorVersion string
|
||||
if ldapInterface != nil {
|
||||
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()
|
||||
}
|
||||
|
||||
// Here we are getting information regarding the database (mysql/postgres + current Mattermost version)
|
||||
databaseType, databaseVersion := a.Srv().DatabaseTypeAndMattermostVersion()
|
||||
|
||||
// Creating the struct for support packet yaml file
|
||||
supportPacket := model.SupportPacket{
|
||||
ServerOS: runtime.GOOS,
|
||||
ServerArchitecture: runtime.GOARCH,
|
||||
DatabaseType: databaseType,
|
||||
DatabaseVersion: databaseVersion,
|
||||
LdapVendorName: vendorName,
|
||||
LdapVendorVersion: vendorVersion,
|
||||
ElasticServerVersion: elasticServerVersion,
|
||||
ElasticServerPlugins: elasticServerPlugins,
|
||||
}
|
||||
|
||||
// Marshal to a Yaml File
|
||||
supportPacketYaml, err := yaml.Marshal(&supportPacket)
|
||||
if err == nil {
|
||||
fileData := model.FileData{
|
||||
Filename: "support_packet.yaml",
|
||||
Body: supportPacketYaml,
|
||||
}
|
||||
return &fileData, ""
|
||||
}
|
||||
|
||||
warning := fmt.Sprintf("yaml.Marshal(&supportPacket) Error: %s", err.Error())
|
||||
return nil, warning
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user