diff --git a/app/server.go b/app/server.go index d0091ae94f..75da8f294f 100644 --- a/app/server.go +++ b/app/server.go @@ -7,11 +7,9 @@ import ( "bytes" "context" "crypto/tls" - "encoding/json" "fmt" "hash/maphash" "html/template" - "io/ioutil" "net" "net/http" "net/http/pprof" @@ -27,8 +25,6 @@ import ( "syscall" "time" - "gopkg.in/yaml.v2" - "github.com/getsentry/sentry-go" sentryhttp "github.com/getsentry/sentry-go/http" "github.com/gorilla/handlers" @@ -2093,183 +2089,6 @@ func (s *Server) SetSharedChannelSyncService(sharedChannelService SharedChannelS s.sharedChannelService = sharedChannelService } -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.Config().NotificationLogSettings.EnableFile { - // notifications.log - notificationsLog := config.GetNotificationsLogFileLocation(*a.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.Config().LogSettings.EnableFile { - // mattermost.log - mattermostLog := config.GetLogFileLocation(*a.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.ch.Ldap - var vendorName, vendorVersion string - if ldapInterface != nil { - vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion() - } - - // Here we are getting information regarding the database (mysql/postgres + current schema version) - databaseType, databaseVersion := a.Srv().DatabaseTypeAndSchemaVersion() - - // Creating the struct for support packet yaml file - supportPacket := model.SupportPacket{ - ServerOS: runtime.GOOS, - ServerArchitecture: runtime.GOARCH, - ServerVersion: model.CurrentVersion, - BuildHash: model.BuildHash, - 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 -} - func (s *Server) GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) { if *s.Config().FileSettings.DriverName == "" { img, appErr := s.GetDefaultProfileImage(user) diff --git a/app/server_test.go b/app/server_test.go index a8daa7ea77..3b127a6e33 100644 --- a/app/server_test.go +++ b/app/server_test.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "net/http" "net/http/httptest" @@ -247,161 +246,6 @@ func TestDatabaseTypeAndMattermostVersion(t *testing.T) { assert.GreaterOrEqual(t, mattermostVersion, strconv.Itoa(1)) } -func TestGenerateSupportPacket(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("mattermost.log", d1, 0777) - require.NoError(t, err) - err = ioutil.WriteFile("notifications.log", d1, 0777) - require.NoError(t, err) - - fileDatas := th.App.GenerateSupportPacket() - testFiles := []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "mattermost.log", "notifications.log"} - for i, fileData := range fileDatas { - require.NotNil(t, fileData) - assert.Equal(t, testFiles[i], fileData.Filename) - assert.Positive(t, len(fileData.Body)) - } - - // Remove these two files and ensure that warning.txt file is generated - err = os.Remove("notifications.log") - require.NoError(t, err) - err = os.Remove("mattermost.log") - require.NoError(t, err) - fileDatas = th.App.GenerateSupportPacket() - testFiles = []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "warning.txt"} - for i, fileData := range fileDatas { - require.NotNil(t, fileData) - assert.Equal(t, testFiles[i], fileData.Filename) - assert.Positive(t, len(fileData.Body)) - } -} - -func TestGetNotificationsLog(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - // Disable notifications file to get an error - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.NotificationLogSettings.EnableFile = false - }) - - fileData, warning := th.App.getNotificationsLog() - assert.Nil(t, fileData) - assert.Equal(t, warning, "Unable to retrieve notifications.log because LogSettings: EnableFile is false in config.json") - - // Enable notifications file but delete any notifications file to get an error trying to read the file - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.NotificationLogSettings.EnableFile = true - }) - - // If any previous notifications.log file, lets delete it - os.Remove("notifications.log") - - fileData, warning = th.App.getNotificationsLog() - assert.Nil(t, fileData) - assert.Contains(t, warning, "ioutil.ReadFile(notificationsLog) Error:") - - // Happy path where we have file and no warning - d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("notifications.log", d1, 0777) - defer os.Remove("notifications.log") - require.NoError(t, err) - - fileData, warning = th.App.getNotificationsLog() - require.NotNil(t, fileData) - assert.Equal(t, "notifications.log", fileData.Filename) - assert.Positive(t, len(fileData.Body)) - assert.Empty(t, warning) -} - -func TestGetMattermostLog(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - // disable mattermost log file setting in config so we should get an warning - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.LogSettings.EnableFile = false - }) - - fileData, warning := th.App.getMattermostLog() - assert.Nil(t, fileData) - assert.Equal(t, "Unable to retrieve mattermost.log because LogSettings: EnableFile is false in config.json", warning) - - // We enable the setting but delete any mattermost log file - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.LogSettings.EnableFile = true - }) - - // If any previous mattermost.log file, lets delete it - os.Remove("mattermost.log") - - fileData, warning = th.App.getMattermostLog() - assert.Nil(t, fileData) - assert.Contains(t, warning, "ioutil.ReadFile(mattermostLog) Error:") - - // Happy path where we get a log file and no warning - d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("mattermost.log", d1, 0777) - defer os.Remove("mattermost.log") - require.NoError(t, err) - - fileData, warning = th.App.getMattermostLog() - require.NotNil(t, fileData) - assert.Equal(t, "mattermost.log", fileData.Filename) - assert.Positive(t, len(fileData.Body)) - assert.Empty(t, warning) -} - -func TestCreateSanitizedConfigFile(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - // Happy path where we have a sanitized config file with no warning - fileData, warning := th.App.createSanitizedConfigFile() - require.NotNil(t, fileData) - assert.Equal(t, "sanitized_config.json", fileData.Filename) - assert.Positive(t, len(fileData.Body)) - assert.Empty(t, warning) -} - -func TestCreatePluginsFile(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - // Happy path where we have a plugins file with no warning - fileData, warning := th.App.createPluginsFile() - require.NotNil(t, fileData) - assert.Equal(t, "plugins.json", fileData.Filename) - assert.Positive(t, len(fileData.Body)) - assert.Empty(t, warning) - - // Turn off plugins so we can get an error - th.App.UpdateConfig(func(cfg *model.Config) { - *cfg.PluginSettings.Enable = false - }) - - // Plugins off in settings so no fileData and we get a warning instead - fileData, warning = th.App.createPluginsFile() - assert.Nil(t, fileData) - assert.Contains(t, warning, "c.App.GetPlugins() Error:") -} - -func TestGenerateSupportPacketYaml(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - // Happy path where we have a support packet yaml file without any warnings - fileData, warning := th.App.generateSupportPacketYaml() - require.NotNil(t, fileData) - assert.Equal(t, "support_packet.yaml", fileData.Filename) - assert.Positive(t, len(fileData.Body)) - assert.Empty(t, warning) - -} - func TestStartServerTLSVersion(t *testing.T) { configStore, _ := config.NewMemoryStore() store, _ := config.NewStoreFromBacking(configStore, nil, false) diff --git a/app/support_packet.go b/app/support_packet.go new file mode 100644 index 0000000000..ea1a6b73ce --- /dev/null +++ b/app/support_packet.go @@ -0,0 +1,206 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package app + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "runtime" + "strings" + + "github.com/mattermost/mattermost-server/v6/config" + "github.com/mattermost/mattermost-server/v6/model" + "github.com/pkg/errors" + "gopkg.in/yaml.v2" +) + +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) 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.ch.Ldap + var vendorName, vendorVersion string + if ldapInterface != nil { + vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion() + } + + // Here we are getting information regarding the database (mysql/postgres + current schema version) + databaseType, databaseVersion := a.Srv().DatabaseTypeAndSchemaVersion() + + uniqueUserCount, err := a.Srv().Store.User().Count(model.UserCountOptions{}) + if err != nil { + return nil, errors.Wrap(err, "error while getting user count").Error() + } + + supportedUsers := 0 + if license := a.Srv().License(); license != nil { + supportedUsers = *license.Features.Users + } + + // Creating the struct for support packet yaml file + supportPacket := model.SupportPacket{ + ServerOS: runtime.GOOS, + ServerArchitecture: runtime.GOARCH, + ServerVersion: model.CurrentVersion, + BuildHash: model.BuildHash, + DatabaseType: databaseType, + DatabaseVersion: databaseVersion, + LdapVendorName: vendorName, + LdapVendorVersion: vendorVersion, + ElasticServerVersion: elasticServerVersion, + ElasticServerPlugins: elasticServerPlugins, + ActiveUsers: int(uniqueUserCount), + LicenseSupportedUsers: supportedUsers, + } + + // 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 +} + +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) getNotificationsLog() (*model.FileData, string) { + var warning string + + // Getting notifications.log + if *a.Config().NotificationLogSettings.EnableFile { + // notifications.log + notificationsLog := config.GetNotificationsLogFileLocation(*a.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.Config().LogSettings.EnableFile { + // mattermost.log + mattermostLog := config.GetLogFileLocation(*a.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 +} diff --git a/app/support_packet_test.go b/app/support_packet_test.go new file mode 100644 index 0000000000..05e7d0418a --- /dev/null +++ b/app/support_packet_test.go @@ -0,0 +1,177 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package app + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/mattermost/mattermost-server/v6/model" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +func TestCreatePluginsFile(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // Happy path where we have a plugins file with no warning + fileData, warning := th.App.createPluginsFile() + require.NotNil(t, fileData) + assert.Equal(t, "plugins.json", fileData.Filename) + assert.Positive(t, len(fileData.Body)) + assert.Empty(t, warning) + + // Turn off plugins so we can get an error + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.PluginSettings.Enable = false + }) + + // Plugins off in settings so no fileData and we get a warning instead + fileData, warning = th.App.createPluginsFile() + assert.Nil(t, fileData) + assert.Contains(t, warning, "c.App.GetPlugins() Error:") +} + +func TestGenerateSupportPacketYaml(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + licenseUsers := 100 + license := model.NewTestLicense() + license.Features.Users = model.NewInt(licenseUsers) + th.App.Srv().SetLicense(license) + + // Happy path where we have a support packet yaml file without any warnings + fileData, warning := th.App.generateSupportPacketYaml() + require.NotNil(t, fileData) + assert.Equal(t, "support_packet.yaml", fileData.Filename) + assert.Positive(t, len(fileData.Body)) + assert.Empty(t, warning) + var packet model.SupportPacket + require.NoError(t, yaml.Unmarshal(fileData.Body, &packet)) + assert.Equal(t, 3, packet.ActiveUsers) // from InitBasic. + assert.Equal(t, licenseUsers, packet.LicenseSupportedUsers) +} +func TestGenerateSupportPacket(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + d1 := []byte("hello\ngo\n") + err := ioutil.WriteFile("mattermost.log", d1, 0777) + require.NoError(t, err) + err = ioutil.WriteFile("notifications.log", d1, 0777) + require.NoError(t, err) + + fileDatas := th.App.GenerateSupportPacket() + testFiles := []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "mattermost.log", "notifications.log"} + for i, fileData := range fileDatas { + require.NotNil(t, fileData) + assert.Equal(t, testFiles[i], fileData.Filename) + assert.Positive(t, len(fileData.Body)) + } + + // Remove these two files and ensure that warning.txt file is generated + err = os.Remove("notifications.log") + require.NoError(t, err) + err = os.Remove("mattermost.log") + require.NoError(t, err) + fileDatas = th.App.GenerateSupportPacket() + testFiles = []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "warning.txt"} + for i, fileData := range fileDatas { + require.NotNil(t, fileData) + assert.Equal(t, testFiles[i], fileData.Filename) + assert.Positive(t, len(fileData.Body)) + } +} + +func TestGetNotificationsLog(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // Disable notifications file to get an error + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.NotificationLogSettings.EnableFile = false + }) + + fileData, warning := th.App.getNotificationsLog() + assert.Nil(t, fileData) + assert.Equal(t, warning, "Unable to retrieve notifications.log because LogSettings: EnableFile is false in config.json") + + // Enable notifications file but delete any notifications file to get an error trying to read the file + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.NotificationLogSettings.EnableFile = true + }) + + // If any previous notifications.log file, lets delete it + os.Remove("notifications.log") + + fileData, warning = th.App.getNotificationsLog() + assert.Nil(t, fileData) + assert.Contains(t, warning, "ioutil.ReadFile(notificationsLog) Error:") + + // Happy path where we have file and no warning + d1 := []byte("hello\ngo\n") + err := ioutil.WriteFile("notifications.log", d1, 0777) + defer os.Remove("notifications.log") + require.NoError(t, err) + + fileData, warning = th.App.getNotificationsLog() + require.NotNil(t, fileData) + assert.Equal(t, "notifications.log", fileData.Filename) + assert.Positive(t, len(fileData.Body)) + assert.Empty(t, warning) +} + +func TestGetMattermostLog(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // disable mattermost log file setting in config so we should get an warning + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.LogSettings.EnableFile = false + }) + + fileData, warning := th.App.getMattermostLog() + assert.Nil(t, fileData) + assert.Equal(t, "Unable to retrieve mattermost.log because LogSettings: EnableFile is false in config.json", warning) + + // We enable the setting but delete any mattermost log file + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.LogSettings.EnableFile = true + }) + + // If any previous mattermost.log file, lets delete it + os.Remove("mattermost.log") + + fileData, warning = th.App.getMattermostLog() + assert.Nil(t, fileData) + assert.Contains(t, warning, "ioutil.ReadFile(mattermostLog) Error:") + + // Happy path where we get a log file and no warning + d1 := []byte("hello\ngo\n") + err := ioutil.WriteFile("mattermost.log", d1, 0777) + defer os.Remove("mattermost.log") + require.NoError(t, err) + + fileData, warning = th.App.getMattermostLog() + require.NotNil(t, fileData) + assert.Equal(t, "mattermost.log", fileData.Filename) + assert.Positive(t, len(fileData.Body)) + assert.Empty(t, warning) +} + +func TestCreateSanitizedConfigFile(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // Happy path where we have a sanitized config file with no warning + fileData, warning := th.App.createSanitizedConfigFile() + require.NotNil(t, fileData) + assert.Equal(t, "sanitized_config.json", fileData.Filename) + assert.Positive(t, len(fileData.Body)) + assert.Empty(t, warning) +} diff --git a/model/system.go b/model/system.go index b84a8dade6..af0e944094 100644 --- a/model/system.go +++ b/model/system.go @@ -73,16 +73,18 @@ type ServerBusyState struct { } type SupportPacket struct { - ServerOS string `yaml:"server_os"` - ServerArchitecture string `yaml:"server_architecture"` - ServerVersion string `yaml:"server_version"` - BuildHash string `yaml:"build_hash,omitempty"` - DatabaseType string `yaml:"database_type"` - DatabaseVersion string `yaml:"database_version"` - LdapVendorName string `yaml:"ldap_vendor_name,omitempty"` - LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"` - ElasticServerVersion string `yaml:"elastic_server_version,omitempty"` - ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"` + ServerOS string `yaml:"server_os"` + ServerArchitecture string `yaml:"server_architecture"` + ServerVersion string `yaml:"server_version"` + BuildHash string `yaml:"build_hash,omitempty"` + DatabaseType string `yaml:"database_type"` + DatabaseVersion string `yaml:"database_version"` + LdapVendorName string `yaml:"ldap_vendor_name,omitempty"` + LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"` + ElasticServerVersion string `yaml:"elastic_server_version,omitempty"` + ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"` + ActiveUsers int `yaml:"active_users"` + LicenseSupportedUsers int `yaml:"license_supported_users,omitempty"` } type FileData struct {