Files
upstream-mirror 240db4e2a7
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:29:55 +05:00

258 lines
7.7 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package commands
import (
"context"
"fmt"
"io"
"os"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/client"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
)
var SystemCmd = &cobra.Command{
Use: "system",
Short: "System management",
Long: `System management commands for interacting with the server state and configuration.`,
}
var SystemGetBusyCmd = &cobra.Command{
Use: "getbusy",
Short: "Get the current busy state",
Long: `Gets the server busy state (high load) and timestamp corresponding to when the server busy flag will be automatically cleared.`,
Example: ` system getbusy`,
Args: cobra.NoArgs,
RunE: withClient(getBusyCmdF),
}
var SystemSetBusyCmd = &cobra.Command{
Use: "setbusy -s [seconds]",
Short: "Set the busy state to true",
Long: `Set the busy state to true for the specified number of seconds, which disables non-critical services.`,
Example: ` system setbusy -s 3600`,
Args: cobra.NoArgs,
RunE: withClient(setBusyCmdF),
}
var SystemClearBusyCmd = &cobra.Command{
Use: "clearbusy",
Short: "Clears the busy state",
Long: `Clear the busy state, which re-enables non-critical services.`,
Example: ` system clearbusy`,
Args: cobra.NoArgs,
RunE: withClient(clearBusyCmdF),
}
var SystemVersionCmd = &cobra.Command{
Use: "version",
Short: "Prints the remote server version",
Long: "Prints the server version of the currently connected Mattermost instance",
Example: ` system version`,
Args: cobra.NoArgs,
RunE: withClient(systemVersionCmdF),
}
var SystemStatusCmd = &cobra.Command{
Use: "status",
Short: "Prints the status of the server",
Long: "Prints the server status calculated using several basic server healthchecks",
Example: ` system status`,
Args: cobra.NoArgs,
RunE: withClient(systemStatusCmdF),
}
var SystemSupportPacketCmd = &cobra.Command{
Use: "supportpacket",
Short: "Download a Support Packet",
Long: "Generate and download a Support Packet of the server to share it with Mattermost Support",
Example: ` system supportpacket`,
Args: cobra.NoArgs,
RunE: withClient(systemSupportPacketCmdF),
}
var SystemNukeCmd = &cobra.Command{
Use: "nuke",
Short: "Destructive operations that permanently delete data",
Long: "Destructive operations that permanently and irreversibly delete server data. Use with extreme caution.",
}
var SystemNukeUsersCmd = &cobra.Command{
Use: "users",
Short: "Delete all users and all posts. Local command only.",
Long: "Permanently delete all users and all related information including posts. This command can only be run in local mode.",
Example: " system nuke users",
Args: cobra.NoArgs,
PreRun: localOnlyPrecheck,
RunE: withClient(nukeUsersCmdF),
}
func init() {
SystemSetBusyCmd.Flags().UintP("seconds", "s", 3600, "Number of seconds until server is automatically marked as not busy.")
_ = SystemSetBusyCmd.MarkFlagRequired("seconds")
SystemSupportPacketCmd.Flags().StringP("output-file", "o", "", "Define the output file name")
SystemNukeUsersCmd.Flags().Bool("confirm", false, "Confirm you really want to permanently delete all users, posts, and related data, and that a DB backup has been performed")
SystemNukeCmd.AddCommand(
SystemNukeUsersCmd,
)
SystemCmd.AddCommand(
SystemGetBusyCmd,
SystemSetBusyCmd,
SystemClearBusyCmd,
SystemVersionCmd,
SystemStatusCmd,
SystemSupportPacketCmd,
SystemNukeCmd,
)
RootCmd.AddCommand(SystemCmd)
}
func getBusyCmdF(c client.Client, cmd *cobra.Command, _ []string) error {
printer.SetSingle(true)
sbs, _, err := c.GetServerBusy(context.TODO())
if err != nil {
return fmt.Errorf("unable to get busy state: %w", err)
}
printer.PrintT("busy:{{.Busy}} expires:{{.Expires_ts}}", sbs)
return nil
}
func setBusyCmdF(c client.Client, cmd *cobra.Command, args []string) error {
printer.SetSingle(true)
seconds, err := cmd.Flags().GetUint("seconds")
if err != nil || seconds == 0 {
return errors.New("seconds must be a number > 0")
}
_, err = c.SetServerBusy(context.TODO(), int(seconds))
if err != nil {
return fmt.Errorf("unable to set busy state: %w", err)
}
printer.PrintT("Busy state set", map[string]string{"status": "ok"})
return nil
}
func clearBusyCmdF(c client.Client, cmd *cobra.Command, _ []string) error {
printer.SetSingle(true)
_, err := c.ClearServerBusy(context.TODO())
if err != nil {
return fmt.Errorf("unable to clear busy state: %w", err)
}
printer.PrintT("Busy state cleared", map[string]string{"status": "ok"})
return nil
}
func systemVersionCmdF(c client.Client, cmd *cobra.Command, _ []string) error {
printer.SetSingle(true)
// server version information comes with all responses. We can't
// use the initial "withClient" connection information as local
// mode doesn't need to log in, so we use an endpoint that will
// always return a valid response
_, resp, err := c.GetPing(context.TODO())
if err != nil {
return fmt.Errorf("unable to fetch server version: %w", err)
}
printer.PrintT("Server version {{.version}}", map[string]string{"version": resp.ServerVersion})
return nil
}
func systemStatusCmdF(c client.Client, cmd *cobra.Command, _ []string) error {
printer.SetSingle(true)
status, _, err := c.GetPingWithOptions(context.TODO(), model.SystemPingOptions{
FullStatus: true,
RESTSemantics: true,
})
if err != nil {
return fmt.Errorf("unable to fetch server status: %w", err)
}
printer.PrintT(`Server status: {{.status}}
Android Latest Version: {{.AndroidLatestVersion}}
Android Minimum Version: {{.AndroidMinVersion}}
Desktop Latest Version: {{.DesktopLatestVersion}}
Desktop Minimum Version: {{.DesktopMinVersion}}
Ios Latest Version: {{.IosLatestVersion}}
Ios Minimum Version: {{.IosMinVersion}}
Database Status: {{.database_status}}
Filestore Status: {{.filestore_status}}`, status)
// Check health status and return non-zero exit code if any component is unhealthy
if status["status"] != model.StatusOk {
return fmt.Errorf("server status is unhealthy: %s", status["status"])
}
if dbStatus, ok := status["database_status"]; ok && dbStatus != model.StatusOk {
return fmt.Errorf("database status is unhealthy: %s", dbStatus)
}
if filestoreStatus, ok := status["filestore_status"]; ok && filestoreStatus != model.StatusOk {
return fmt.Errorf("filestore status is unhealthy: %s", filestoreStatus)
}
return nil
}
func systemSupportPacketCmdF(c client.Client, cmd *cobra.Command, _ []string) error {
printer.SetSingle(true)
filename, err := cmd.Flags().GetString("output-file")
if err != nil {
return err
}
printer.Print("Downloading Support Packet")
data, rFilename, _, err := c.GenerateSupportPacket(context.TODO())
if err != nil {
return fmt.Errorf("unable to fetch Support Packet: %w", err)
}
if filename == "" {
filename = rFilename
}
file, err := os.Create(filename)
if err != nil {
return fmt.Errorf("failed to create zip file: %w", err)
}
_, err = io.Copy(file, data)
if err != nil {
return fmt.Errorf("failed to write to zip file: %w", err)
}
printer.PrintT("Downloaded Support Packet to {{ .filename }}", map[string]string{"filename": filename})
return nil
}
func nukeUsersCmdF(c client.Client, cmd *cobra.Command, args []string) error {
confirmFlag, _ := cmd.Flags().GetBool("confirm")
if !confirmFlag {
if err := getConfirmation("Are you sure you want to permanently delete all users, posts, and related data?", true); err != nil {
return err
}
}
if _, err := c.PermanentDeleteAllUsers(context.TODO()); err != nil {
return err
}
defer printer.Print("All users successfully deleted")
return nil
}