[MM-54318] Add file storage information to support package (#24474)
* Reorder stats in support package struct * Add file storage information to support package * Add clusterID * Change method name to DriverName * Ordering * Fix test
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
4482ba0fd0
Коммит
b2f36c7cdf
@@ -59,7 +59,36 @@ func (a *App) GenerateSupportPacket() []model.FileData {
|
|||||||
func (a *App) generateSupportPacketYaml() (*model.FileData, error) {
|
func (a *App) generateSupportPacketYaml() (*model.FileData, error) {
|
||||||
var rErr error
|
var rErr error
|
||||||
|
|
||||||
// Here we are getting information regarding Elastic Search
|
/* DB */
|
||||||
|
|
||||||
|
databaseType, databaseSchemaVersion := a.Srv().DatabaseTypeAndSchemaVersion()
|
||||||
|
databaseVersion, _ := a.Srv().Store().GetDbVersion(false)
|
||||||
|
|
||||||
|
/* Cluster */
|
||||||
|
|
||||||
|
var clusterID string
|
||||||
|
if a.Cluster() != nil {
|
||||||
|
clusterID = a.Cluster().GetClusterId()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File store */
|
||||||
|
|
||||||
|
fileDriver := a.Srv().Platform().FileBackend().DriverName()
|
||||||
|
fileStatus := model.StatusOk
|
||||||
|
err := a.Srv().Platform().FileBackend().TestConnection()
|
||||||
|
if err != nil {
|
||||||
|
fileStatus = model.StatusFail + ": " + err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LDAP */
|
||||||
|
|
||||||
|
var vendorName, vendorVersion string
|
||||||
|
if ldapInterface := a.ch.Ldap; a.ch.Ldap != nil {
|
||||||
|
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Elastic Search */
|
||||||
|
|
||||||
var elasticServerVersion string
|
var elasticServerVersion string
|
||||||
var elasticServerPlugins []string
|
var elasticServerPlugins []string
|
||||||
if a.Srv().Platform().SearchEngine.ElasticsearchEngine != nil {
|
if a.Srv().Platform().SearchEngine.ElasticsearchEngine != nil {
|
||||||
@@ -67,16 +96,16 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, error) {
|
|||||||
elasticServerPlugins = a.Srv().Platform().SearchEngine.ElasticsearchEngine.GetPlugins()
|
elasticServerPlugins = a.Srv().Platform().SearchEngine.ElasticsearchEngine.GetPlugins()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we are getting information regarding LDAP
|
/* License */
|
||||||
ldapInterface := a.ch.Ldap
|
|
||||||
var vendorName, vendorVersion string
|
licenseTo := ""
|
||||||
if ldapInterface != nil {
|
supportedUsers := 0
|
||||||
vendorName, vendorVersion = ldapInterface.GetVendorNameAndVendorVersion()
|
if license := a.Srv().License(); license != nil {
|
||||||
|
supportedUsers = *license.Features.Users
|
||||||
|
licenseTo = license.Customer.Company
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we are getting information regarding the database (mysql/postgres + current schema version)
|
/* Jobs */
|
||||||
databaseType, databaseSchemaVersion := a.Srv().DatabaseTypeAndSchemaVersion()
|
|
||||||
databaseVersion, _ := a.Srv().Store().GetDbVersion(false)
|
|
||||||
|
|
||||||
uniqueUserCount, err := a.Srv().Store().User().Count(model.UserCountOptions{})
|
uniqueUserCount, err := a.Srv().Store().User().Count(model.UserCountOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -112,31 +141,42 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, error) {
|
|||||||
rErr = multierror.Append(errors.Wrap(err, "error while getting migration jobs"))
|
rErr = multierror.Append(errors.Wrap(err, "error while getting migration jobs"))
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseTo := ""
|
|
||||||
supportedUsers := 0
|
|
||||||
if license := a.Srv().License(); license != nil {
|
|
||||||
supportedUsers = *license.Features.Users
|
|
||||||
licenseTo = license.Customer.Company
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creating the struct for support packet yaml file
|
// Creating the struct for support packet yaml file
|
||||||
supportPacket := model.SupportPacket{
|
supportPacket := model.SupportPacket{
|
||||||
LicenseTo: licenseTo,
|
/* Build information */
|
||||||
ServerOS: runtime.GOOS,
|
ServerOS: runtime.GOOS,
|
||||||
ServerArchitecture: runtime.GOARCH,
|
ServerArchitecture: runtime.GOARCH,
|
||||||
ServerVersion: model.CurrentVersion,
|
ServerVersion: model.CurrentVersion,
|
||||||
BuildHash: model.BuildHash,
|
BuildHash: model.BuildHash,
|
||||||
|
|
||||||
|
/* DB */
|
||||||
DatabaseType: databaseType,
|
DatabaseType: databaseType,
|
||||||
DatabaseVersion: databaseVersion,
|
DatabaseVersion: databaseVersion,
|
||||||
DatabaseSchemaVersion: databaseSchemaVersion,
|
DatabaseSchemaVersion: databaseSchemaVersion,
|
||||||
LdapVendorName: vendorName,
|
|
||||||
LdapVendorVersion: vendorVersion,
|
/* Cluster */
|
||||||
ElasticServerVersion: elasticServerVersion,
|
ClusterID: clusterID,
|
||||||
ElasticServerPlugins: elasticServerPlugins,
|
|
||||||
ActiveUsers: int(uniqueUserCount),
|
/* File store */
|
||||||
|
FileDriver: fileDriver,
|
||||||
|
FileStatus: fileStatus,
|
||||||
|
|
||||||
|
/* LDAP */
|
||||||
|
LdapVendorName: vendorName,
|
||||||
|
LdapVendorVersion: vendorVersion,
|
||||||
|
|
||||||
|
/* Elastic Search */
|
||||||
|
ElasticServerVersion: elasticServerVersion,
|
||||||
|
ElasticServerPlugins: elasticServerPlugins,
|
||||||
|
|
||||||
|
/* License */
|
||||||
|
LicenseTo: licenseTo,
|
||||||
LicenseSupportedUsers: supportedUsers,
|
LicenseSupportedUsers: supportedUsers,
|
||||||
|
|
||||||
// Jobs
|
/* Server stats */
|
||||||
|
ActiveUsers: int(uniqueUserCount),
|
||||||
|
|
||||||
|
/* Jobs */
|
||||||
DataRetentionJobs: dataRetentionJobs,
|
DataRetentionJobs: dataRetentionJobs,
|
||||||
MessageExportJobs: messageExportJobs,
|
MessageExportJobs: messageExportJobs,
|
||||||
ElasticPostIndexingJobs: elasticPostIndexingJobs,
|
ElasticPostIndexingJobs: elasticPostIndexingJobs,
|
||||||
@@ -146,6 +186,8 @@ func (a *App) generateSupportPacketYaml() (*model.FileData, error) {
|
|||||||
MigrationJobs: migrationJobs,
|
MigrationJobs: migrationJobs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Server stats */
|
||||||
|
|
||||||
analytics, appErr := a.GetAnalytics("standard", "")
|
analytics, appErr := a.GetAnalytics("standard", "")
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
rErr = multierror.Append(errors.Wrap(appErr, "error while getting analytics"))
|
rErr = multierror.Append(errors.Wrap(appErr, "error while getting analytics"))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost/server/public/model"
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
"github.com/mattermost/mattermost/server/v8/channels/app/platform"
|
||||||
|
fmocks "github.com/mattermost/mattermost/server/v8/platform/shared/filestore/mocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreatePluginsFile(t *testing.T) {
|
func TestCreatePluginsFile(t *testing.T) {
|
||||||
@@ -45,16 +48,42 @@ func TestGenerateSupportPacketYaml(t *testing.T) {
|
|||||||
license.Features.Users = model.NewInt(licenseUsers)
|
license.Features.Users = model.NewInt(licenseUsers)
|
||||||
th.App.Srv().SetLicense(license)
|
th.App.Srv().SetLicense(license)
|
||||||
|
|
||||||
// Happy path where we have a support packet yaml file without any warnings
|
t.Run("Happy path", func(t *testing.T) {
|
||||||
fileData, err := th.App.generateSupportPacketYaml()
|
// Happy path where we have a support packet yaml file without any warnings
|
||||||
require.NotNil(t, fileData)
|
|
||||||
assert.Equal(t, "support_packet.yaml", fileData.Filename)
|
fileData, err := th.App.generateSupportPacketYaml()
|
||||||
assert.Positive(t, len(fileData.Body))
|
require.NotNil(t, fileData)
|
||||||
assert.NoError(t, err)
|
assert.Equal(t, "support_packet.yaml", fileData.Filename)
|
||||||
var packet model.SupportPacket
|
assert.Positive(t, len(fileData.Body))
|
||||||
require.NoError(t, yaml.Unmarshal(fileData.Body, &packet))
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 3, packet.ActiveUsers) // from InitBasic.
|
var packet model.SupportPacket
|
||||||
assert.Equal(t, licenseUsers, packet.LicenseSupportedUsers)
|
require.NoError(t, yaml.Unmarshal(fileData.Body, &packet))
|
||||||
|
|
||||||
|
assert.Equal(t, 3, packet.ActiveUsers) // from InitBasic.
|
||||||
|
assert.Equal(t, licenseUsers, packet.LicenseSupportedUsers)
|
||||||
|
assert.Empty(t, packet.ClusterID)
|
||||||
|
assert.Equal(t, "local", packet.FileDriver)
|
||||||
|
assert.Equal(t, "OK", packet.FileStatus)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("filestore fails", func(t *testing.T) {
|
||||||
|
fb := &fmocks.FileBackend{}
|
||||||
|
platform.SetFileStore(fb)(th.Server.Platform())
|
||||||
|
fb.On("DriverName").Return("mock")
|
||||||
|
fb.On("TestConnection").Return(errors.New("all broken"))
|
||||||
|
|
||||||
|
fileData, err := th.App.generateSupportPacketYaml()
|
||||||
|
require.NotNil(t, fileData)
|
||||||
|
assert.Equal(t, "support_packet.yaml", fileData.Filename)
|
||||||
|
assert.Positive(t, len(fileData.Body))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
var packet model.SupportPacket
|
||||||
|
require.NoError(t, yaml.Unmarshal(fileData.Body, &packet))
|
||||||
|
|
||||||
|
assert.Equal(t, "mock", packet.FileDriver)
|
||||||
|
assert.Equal(t, "FAIL: all broken", packet.FileStatus)
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateSupportPacket(t *testing.T) {
|
func TestGenerateSupportPacket(t *testing.T) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type ReadCloseSeeker interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FileBackend interface {
|
type FileBackend interface {
|
||||||
|
DriverName() string
|
||||||
TestConnection() error
|
TestConnection() error
|
||||||
|
|
||||||
Reader(path string) (ReadCloseSeeker, error)
|
Reader(path string) (ReadCloseSeeker, error)
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ func copyFile(src, dst string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LocalFileBackend) DriverName() string {
|
||||||
|
return driverLocal
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LocalFileBackend) TestConnection() error {
|
func (b *LocalFileBackend) TestConnection() error {
|
||||||
f := bytes.NewReader([]byte("testingwrite"))
|
f := bytes.NewReader([]byte("testingwrite"))
|
||||||
if _, err := writeFileLocally(f, filepath.Join(b.directory, TestFilePath)); err != nil {
|
if _, err := writeFileLocally(f, filepath.Join(b.directory, TestFilePath)); err != nil {
|
||||||
|
|||||||
@@ -57,6 +57,20 @@ func (_m *FileBackend) CopyFile(oldPath string, newPath string) error {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DriverName provides a mock function with given fields:
|
||||||
|
func (_m *FileBackend) DriverName() string {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func() string); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// FileExists provides a mock function with given fields: path
|
// FileExists provides a mock function with given fields: path
|
||||||
func (_m *FileBackend) FileExists(path string) (bool, error) {
|
func (_m *FileBackend) FileExists(path string) (bool, error) {
|
||||||
ret := _m.Called(path)
|
ret := _m.Called(path)
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ func (b *S3FileBackend) s3New(isCloud bool) (*s3.Client, error) {
|
|||||||
return s3Clnt, nil
|
return s3Clnt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *S3FileBackend) DriverName() string {
|
||||||
|
return driverS3
|
||||||
|
}
|
||||||
|
|
||||||
func (b *S3FileBackend) TestConnection() error {
|
func (b *S3FileBackend) TestConnection() error {
|
||||||
exists := true
|
exists := true
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@@ -78,31 +78,58 @@ type ServerBusyState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SupportPacket struct {
|
type SupportPacket struct {
|
||||||
LicenseTo string `yaml:"license_to"`
|
/* Build information */
|
||||||
ServerOS string `yaml:"server_os"`
|
|
||||||
ServerArchitecture string `yaml:"server_architecture"`
|
ServerOS string `yaml:"server_os"`
|
||||||
ServerVersion string `yaml:"server_version"`
|
ServerArchitecture string `yaml:"server_architecture"`
|
||||||
BuildHash string `yaml:"build_hash,omitempty"`
|
ServerVersion string `yaml:"server_version"`
|
||||||
DatabaseType string `yaml:"database_type"`
|
BuildHash string `yaml:"build_hash,omitempty"`
|
||||||
DatabaseVersion string `yaml:"database_version"`
|
|
||||||
DatabaseSchemaVersion string `yaml:"database_schema_version"`
|
/* DB */
|
||||||
LdapVendorName string `yaml:"ldap_vendor_name,omitempty"`
|
|
||||||
LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"`
|
DatabaseType string `yaml:"database_type"`
|
||||||
ElasticServerVersion string `yaml:"elastic_server_version,omitempty"`
|
DatabaseVersion string `yaml:"database_version"`
|
||||||
ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"`
|
DatabaseSchemaVersion string `yaml:"database_schema_version"`
|
||||||
ActiveUsers int `yaml:"active_users"`
|
WebsocketConnections int `yaml:"websocket_connections"`
|
||||||
LicenseSupportedUsers int `yaml:"license_supported_users,omitempty"`
|
MasterDbConnections int `yaml:"master_db_connections"`
|
||||||
TotalChannels int `yaml:"total_channels"`
|
ReplicaDbConnections int `yaml:"read_db_connections"`
|
||||||
TotalPosts int `yaml:"total_posts"`
|
|
||||||
TotalTeams int `yaml:"total_teams"`
|
/* Cluster */
|
||||||
DailyActiveUsers int `yaml:"daily_active_users"`
|
|
||||||
MonthlyActiveUsers int `yaml:"monthly_active_users"`
|
ClusterID string `yaml:"cluster_id"`
|
||||||
WebsocketConnections int `yaml:"websocket_connections"`
|
|
||||||
MasterDbConnections int `yaml:"master_db_connections"`
|
/* File store */
|
||||||
ReplicaDbConnections int `yaml:"read_db_connections"`
|
|
||||||
InactiveUserCount int `yaml:"inactive_user_count"`
|
FileDriver string `yaml:"file_driver"`
|
||||||
|
FileStatus string `yaml:"file_status"`
|
||||||
|
|
||||||
|
/* LDAP */
|
||||||
|
|
||||||
|
LdapVendorName string `yaml:"ldap_vendor_name,omitempty"`
|
||||||
|
LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"`
|
||||||
|
|
||||||
|
/* Elastic Search */
|
||||||
|
|
||||||
|
ElasticServerVersion string `yaml:"elastic_server_version,omitempty"`
|
||||||
|
ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"`
|
||||||
|
|
||||||
|
/* License */
|
||||||
|
|
||||||
|
LicenseTo string `yaml:"license_to"`
|
||||||
|
LicenseSupportedUsers int `yaml:"license_supported_users,omitempty"`
|
||||||
|
|
||||||
|
/* Server stats */
|
||||||
|
|
||||||
|
ActiveUsers int `yaml:"active_users"`
|
||||||
|
DailyActiveUsers int `yaml:"daily_active_users"`
|
||||||
|
MonthlyActiveUsers int `yaml:"monthly_active_users"`
|
||||||
|
InactiveUserCount int `yaml:"inactive_user_count"`
|
||||||
|
TotalPosts int `yaml:"total_posts"`
|
||||||
|
TotalChannels int `yaml:"total_channels"`
|
||||||
|
TotalTeams int `yaml:"total_teams"`
|
||||||
|
|
||||||
|
/* Jobs */
|
||||||
|
|
||||||
// Jobs
|
|
||||||
DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
|
DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
|
||||||
MessageExportJobs []*Job `yaml:"message_export_jobs"`
|
MessageExportJobs []*Job `yaml:"message_export_jobs"`
|
||||||
ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
|
ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user