Make support packet composable with plugins (#26403)

---------

Co-authored-by: Ben Schumacher <ben.schumacher@mattermost.com>
Этот коммит содержится в:
Ibrahim Serdar Acikgoz
2024-04-12 10:05:58 +02:00
коммит произвёл GitHub
родитель 165b5ea821
Коммит 92f11f8971
19 изменённых файлов: 505 добавлений и 158 удалений

93
server/public/model/support_packet.go Обычный файл
Просмотреть файл

@@ -0,0 +1,93 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"encoding/json"
"io"
)
type SupportPacket struct {
/* Build information */
ServerOS string `yaml:"server_os"`
ServerArchitecture string `yaml:"server_architecture"`
ServerVersion string `yaml:"server_version"`
BuildHash string `yaml:"build_hash"`
/* DB */
DatabaseType string `yaml:"database_type"`
DatabaseVersion string `yaml:"database_version"`
DatabaseSchemaVersion string `yaml:"database_schema_version"`
WebsocketConnections int `yaml:"websocket_connections"`
MasterDbConnections int `yaml:"master_db_connections"`
ReplicaDbConnections int `yaml:"read_db_connections"`
/* Cluster */
ClusterID string `yaml:"cluster_id"`
/* File store */
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"`
LicenseIsTrial bool `yaml:"license_is_trial,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 */
DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
MessageExportJobs []*Job `yaml:"message_export_jobs"`
ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
ElasticPostAggregationJobs []*Job `yaml:"elastic_post_aggregation_jobs"`
BlevePostIndexingJobs []*Job `yaml:"bleve_post_indexin_jobs"`
LdapSyncJobs []*Job `yaml:"ldap_sync_jobs"`
MigrationJobs []*Job `yaml:"migration_jobs"`
}
type FileData struct {
Filename string
Body []byte
}
type SupportPacketOptions struct {
IncludeLogs bool `json:"include_logs"` // IncludeLogs is the option to include server logs
PluginPackets []string `json:"plugin_packets"` // PluginPackets is a list of pluginids to call hooks
}
// SupportPacketOptionsFromReader decodes a json-encoded request from the given io.Reader.
func SupportPacketOptionsFromReader(reader io.Reader) (*SupportPacketOptions, error) {
var r *SupportPacketOptions
err := json.NewDecoder(reader).Decode(&r)
if err != nil {
return nil, err
}
return r, nil
}

Просмотреть файл

@@ -78,73 +78,6 @@ type ServerBusyState struct {
ExpiresTS string `json:"expires_ts,omitempty"`
}
type SupportPacket struct {
/* Build information */
ServerOS string `yaml:"server_os"`
ServerArchitecture string `yaml:"server_architecture"`
ServerVersion string `yaml:"server_version"`
BuildHash string `yaml:"build_hash"`
/* DB */
DatabaseType string `yaml:"database_type"`
DatabaseVersion string `yaml:"database_version"`
DatabaseSchemaVersion string `yaml:"database_schema_version"`
WebsocketConnections int `yaml:"websocket_connections"`
MasterDbConnections int `yaml:"master_db_connections"`
ReplicaDbConnections int `yaml:"read_db_connections"`
/* Cluster */
ClusterID string `yaml:"cluster_id"`
/* File store */
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"`
LicenseIsTrial bool `yaml:"license_is_trial,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 */
DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
MessageExportJobs []*Job `yaml:"message_export_jobs"`
ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
ElasticPostAggregationJobs []*Job `yaml:"elastic_post_aggregation_jobs"`
BlevePostIndexingJobs []*Job `yaml:"bleve_post_indexin_jobs"`
LdapSyncJobs []*Job `yaml:"ldap_sync_jobs"`
MigrationJobs []*Job `yaml:"migration_jobs"`
}
type FileData struct {
Filename string
Body []byte
}
type AppliedMigration struct {
Version int `json:"version"`
Name string `json:"name"`

Просмотреть файл

@@ -1125,6 +1125,42 @@ func (s *hooksRPCServer) OnSharedChannelsProfileImageSyncMsg(args *Z_OnSharedCha
return nil
}
func init() {
hookNameToId["GenerateSupportData"] = GenerateSupportDataID
}
type Z_GenerateSupportDataArgs struct {
A *Context
}
type Z_GenerateSupportDataReturns struct {
A []*model.FileData
B error
}
func (g *hooksRPCClient) GenerateSupportData(c *Context) ([]*model.FileData, error) {
_args := &Z_GenerateSupportDataArgs{c}
_returns := &Z_GenerateSupportDataReturns{}
if g.implemented[GenerateSupportDataID] {
if err := g.client.Call("Plugin.GenerateSupportData", _args, _returns); err != nil {
g.log.Error("RPC call GenerateSupportData to plugin failed.", mlog.Err(err))
}
}
return _returns.A, _returns.B
}
func (s *hooksRPCServer) GenerateSupportData(args *Z_GenerateSupportDataArgs, returns *Z_GenerateSupportDataReturns) error {
if hook, ok := s.impl.(interface {
GenerateSupportData(c *Context) ([]*model.FileData, error)
}); ok {
returns.A, returns.B = hook.GenerateSupportData(args.A)
returns.B = encodableError(returns.B)
} else {
return encodableError(fmt.Errorf("Hook GenerateSupportData called but not implemented."))
}
return nil
}
type Z_RegisterCommandArgs struct {
A *model.Command
}

Просмотреть файл

@@ -60,6 +60,7 @@ const (
PreferencesHaveChangedID = 42
OnSharedChannelsAttachmentSyncMsgID = 43
OnSharedChannelsProfileImageSyncMsgID = 44
GenerateSupportDataID = 45
TotalHooksID = iota
)
@@ -382,4 +383,10 @@ type Hooks interface {
//
// Minimum server version: 9.5
OnSharedChannelsProfileImageSyncMsg(user *model.User, rc *model.RemoteCluster) error
// GenerateSupportData is invoked when a Support Packet gets generated.
// It allows plugins to include their own content in the Support Packet.
//
// Minimum server version: 9.8
GenerateSupportData(c *Context) ([]*model.FileData, error)
}

Просмотреть файл

@@ -284,3 +284,10 @@ func (hooks *hooksTimerLayer) OnSharedChannelsProfileImageSyncMsg(user *model.Us
hooks.recordTime(startTime, "OnSharedChannelsProfileImageSyncMsg", _returnsA == nil)
return _returnsA
}
func (hooks *hooksTimerLayer) GenerateSupportData(c *Context) ([]*model.FileData, error) {
startTime := timePkg.Now()
_returnsA, _returnsB := hooks.hooksImpl.GenerateSupportData(c)
hooks.recordTime(startTime, "GenerateSupportData", _returnsB == nil)
return _returnsA, _returnsB
}

Просмотреть файл

@@ -105,6 +105,32 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
return r0, r1
}
// GenerateSupportData provides a mock function with given fields: c
func (_m *Hooks) GenerateSupportData(c *plugin.Context) ([]*model.FileData, error) {
ret := _m.Called(c)
var r0 []*model.FileData
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context) ([]*model.FileData, error)); ok {
return rf(c)
}
if rf, ok := ret.Get(0).(func(*plugin.Context) []*model.FileData); ok {
r0 = rf(c)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.FileData)
}
}
if rf, ok := ret.Get(1).(func(*plugin.Context) error); ok {
r1 = rf(c)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Implemented provides a mock function with given fields:
func (_m *Hooks) Implemented() ([]string, error) {
ret := _m.Called()