[MM-64844] Remove deprecated mmctl commands and flags (#33435)

* Remove deprecated mmctl commands and flags

  Remove the following deprecated commands:
  - `channel add` (use `channel users add`)
  - `channel remove` (use `channel users remove`)
  - `channel restore` (use `channel unarchive`)
  - `channel make-private` (use `channel modify --private`)
  - `command delete` (use `command archive`)
  - `permissions show` (use `permissions role show`)

  Remove the following deprecated flags:
  - `--config-path` (use `--config`)
  - `--display_name` (use `--display-name`)
  - `--system_admin` (use `--system-admin`)
  - `--email_verified` (use `--email-verified`)
  - `--attachments` from export create
  - `--resume` from export download
This commit is contained in:
Ben Schumacher
2025-07-18 11:08:29 +02:00
committed by GitHub
parent 4df1b70418
commit ae35dd93a9
13 changed files with 12 additions and 188 deletions
@@ -16,8 +16,6 @@ var VersionCmd = &cobra.Command{
}
func init() {
VersionCmd.Flags().Bool("skip-server-start", false, "Skip the server initialization and return the Mattermost version without the DB version.")
VersionCmd.Flags().MarkDeprecated("skip-server-start", "This flag is not necessary anymore and the flag will be removed in the future releases. Consider removing it from your scripts.")
RootCmd.AddCommand(VersionCmd)
}
-35
View File
@@ -9,12 +9,9 @@ import (
"os/user"
"path/filepath"
"strings"
"sync"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
)
const (
@@ -28,8 +25,6 @@ const (
xdgConfigHomeVar = "$XDG_CONFIG_HOME"
)
var once sync.Once
type Credentials struct {
Name string `json:"name"`
Username string `json:"username"`
@@ -60,37 +55,7 @@ func getDefaultConfigHomePath() string {
return filepath.Join(currentUser.HomeDir, ".config")
}
func resolveLegacyConfigFilePath() string {
configPath := viper.GetString("config-path")
// We use the .mmctl file name (hidden) if the config is in $HOME directory.
// If we were using other directory (e.g. XDG_CONFIG_HOME) we go with mmctl file name.
switch configPath {
case "$HOME":
res := strings.Replace(configPath, userHomeVar, currentUser.HomeDir, 1)
return filepath.Join(res, ".mmctl")
case currentUser.HomeDir:
return filepath.Join(configPath, ".mmctl")
default:
return filepath.Join(configPath, "mmctl")
}
}
func resolveConfigFilePath() string {
// we warn users that config-path is deprecated
suppressWarnings := viper.GetBool("suppress-warnings")
if viper.IsSet("config-path") {
if !suppressWarnings {
once.Do(func() {
printer.PrintWarning("Since mmctl v6 we have been deprecated the --config-path and started to use --config flag instead.\n" +
"Please use --config flag to set config file. (note that --config-path was pointing to a directory)\n\n" +
"After moving your config file to new directory, please unset the --config-path flag or MMCTL_CONFIG_PATH environment variable.\n")
})
}
return resolveLegacyConfigFilePath()
}
// resolve env vars if there are any
fpath := strings.Replace(viper.GetString("config"), userHomeVar, currentUser.HomeDir, 1)
+3 -80
View File
@@ -45,25 +45,6 @@ var ChannelRenameCmd = &cobra.Command{
RunE: withClient(renameChannelCmdF),
}
var RemoveChannelUsersCmd = &cobra.Command{
Use: "remove [channel] [users]",
Short: "Remove users from channel",
Long: "Remove some users from channel",
Example: ` channel remove myteam:mychannel user@example.com username
channel remove myteam:mychannel --all-users`,
Deprecated: "please use \"mmctl channel users remove\" instead",
RunE: withClient(channelUsersRemoveCmdF),
}
var AddChannelUsersCmd = &cobra.Command{
Use: "add [channel] [users]",
Short: "Add users to channel",
Long: "Add some users to channel",
Example: " channel add myteam:mychannel user@example.com username",
Deprecated: "please use \"mmctl channel users add\" instead",
RunE: withClient(channelUsersAddCmdF),
}
var ArchiveChannelsCmd = &cobra.Command{
Use: "archive [channels]",
Short: "Archive channels",
@@ -107,16 +88,6 @@ Channel can be specified by [team]:[channel]. ie. myteam:mychannel or by channel
RunE: withClient(modifyChannelCmdF),
}
var RestoreChannelsCmd = &cobra.Command{
Use: "restore [channels]",
Short: "Restore some channels",
Long: `Restore a previously deleted channel
Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
Example: " channel restore myteam:mychannel",
Deprecated: "please use \"mmctl channel unarchive\" instead",
RunE: withClient(unarchiveChannelsCmdF),
}
var UnarchiveChannelCmd = &cobra.Command{
Use: "unarchive [channels]",
Short: "Unarchive some channels",
@@ -126,17 +97,6 @@ Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channe
RunE: withClient(unarchiveChannelsCmdF),
}
var MakeChannelPrivateCmd = &cobra.Command{
Use: "make-private [channel]",
Aliases: []string{"make_private"},
Short: "Set a channel's type to private",
Long: `Set the type of a channel from Public to Private.
Channel can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
Example: " channel make-private myteam:mychannel",
Deprecated: "please use \"mmctl channel modify --private\" instead",
RunE: withClient(makeChannelPrivateCmdF),
}
var SearchChannelCmd = &cobra.Command{
Use: "search [channel]\n mmctl search --team [team] [channel]",
Short: "Search a channel",
@@ -162,8 +122,6 @@ Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channe
func init() {
ChannelCreateCmd.Flags().String("name", "", "Channel Name")
ChannelCreateCmd.Flags().String("display-name", "", "Channel Display Name")
ChannelCreateCmd.Flags().String("display_name", "", "")
_ = ChannelCreateCmd.Flags().MarkDeprecated("display_name", "please use display-name instead")
ChannelCreateCmd.Flags().String("team", "", "Team name or ID")
ChannelCreateCmd.Flags().String("header", "", "Channel header")
ChannelCreateCmd.Flags().String("purpose", "", "Channel purpose")
@@ -174,10 +132,6 @@ func init() {
ChannelRenameCmd.Flags().String("name", "", "Channel Name")
ChannelRenameCmd.Flags().String("display-name", "", "Channel Display Name")
ChannelRenameCmd.Flags().String("display_name", "", "")
_ = ChannelRenameCmd.Flags().MarkDeprecated("display_name", "please use display-name instead")
RemoveChannelUsersCmd.Flags().Bool("all-users", false, "Remove all users from the indicated channel.")
SearchChannelCmd.Flags().String("team", "", "Team name or ID")
@@ -187,13 +141,9 @@ func init() {
ChannelCmd.AddCommand(
ChannelCreateCmd,
RemoveChannelUsersCmd,
AddChannelUsersCmd,
ArchiveChannelsCmd,
ListChannelsCmd,
RestoreChannelsCmd,
UnarchiveChannelCmd,
MakeChannelPrivateCmd,
ModifyChannelCmd,
ChannelRenameCmd,
SearchChannelCmd,
@@ -213,10 +163,7 @@ func createChannelCmdF(c client.Client, cmd *cobra.Command, args []string) error
}
displayname, errdn := cmd.Flags().GetString("display-name")
if errdn != nil || displayname == "" {
displayname, errdn = cmd.Flags().GetString("display_name")
if errdn != nil || displayname == "" {
return errors.New("display Name is required")
}
return errors.New("display-name is required")
}
teamArg, errteam := cmd.Flags().GetString("team")
if errteam != nil || teamArg == "" {
@@ -388,27 +335,6 @@ func unarchiveChannelsCmdF(c client.Client, cmd *cobra.Command, args []string) e
return errs.ErrorOrNil()
}
func makeChannelPrivateCmdF(c client.Client, cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("enter one channel to modify")
}
channel := getChannelFromChannelArg(c, args[0])
if channel == nil {
return errors.Errorf("unable to find channel %q", args[0])
}
if !(channel.Type == model.ChannelTypeOpen) {
return errors.New("you can only change the type of public channels")
}
if _, _, err := c.UpdateChannelPrivacy(context.TODO(), channel.Id, model.ChannelTypePrivate); err != nil {
return err
}
return nil
}
func modifyChannelCmdF(c client.Client, cmd *cobra.Command, args []string) error {
public, _ := cmd.Flags().GetBool("public")
private, _ := cmd.Flags().GetBool("private")
@@ -447,11 +373,8 @@ func renameChannelCmdF(c client.Client, cmd *cobra.Command, args []string) error
}
newDisplayName, err := cmd.Flags().GetString("display-name")
if err != nil || newDisplayName == "" {
newDisplayName, err = cmd.Flags().GetString("display_name")
if err != nil {
return err
}
if err != nil {
return err
}
// At least one of display name or name flag must be present
+1 -3
View File
@@ -1912,7 +1912,6 @@ func (s *MmctlUnitTestSuite) TestRenameChannelCmd() {
cmd.Flags().String("name", "", "Channel Name")
cmd.Flags().String("display-name", "", channelDisplayName)
cmd.Flags().String("display_name", "", "")
err := renameChannelCmdF(s.client, cmd, args)
s.Require().EqualError(err, "require at least one flag to rename channel, either 'name' or 'display-name'")
@@ -2275,7 +2274,6 @@ func (s *MmctlUnitTestSuite) TestRenameChannelCmd() {
newChannelDisplayName := ""
cmd.Flags().String("name", newChannelName, "Channel Name")
cmd.Flags().String("display-name", newChannelDisplayName, channelDisplayName)
cmd.Flags().String("display_name", "", "")
foundTeam := &model.Team{
Id: teamID,
@@ -2577,7 +2575,7 @@ func (s *MmctlUnitTestSuite) TestCreateChannelCmd() {
cmd.Flags().String("name", channelName, "Channel Name")
err := createChannelCmdF(s.client, cmd, args)
s.Require().EqualError(err, "display Name is required")
s.Require().EqualError(err, "display-name is required")
})
s.Run("should not create channel without name", func() {
-11
View File
@@ -40,16 +40,6 @@ var CommandListCmd = &cobra.Command{
RunE: withClient(listCommandCmdF),
}
var CommandDeleteCmd = &cobra.Command{
Use: "delete [commandID]",
Short: "Delete a slash command",
Long: `Delete a slash command. Commands can be specified by command ID.`,
Example: ` command delete commandID`,
Deprecated: "please use \"mmctl channel archive\" instead",
Args: cobra.ExactArgs(1),
RunE: withClient(archiveCommandCmdF),
}
var CommandArchiveCmd = &cobra.Command{
Use: "archive [commandID]",
Short: "Archive a slash command",
@@ -113,7 +103,6 @@ func init() {
CommandCmd.AddCommand(
CommandCreateCmd,
CommandListCmd,
CommandDeleteCmd,
CommandModifyCmd,
CommandMoveCmd,
CommandShowCmd,
@@ -338,7 +338,7 @@ func (s *MmctlE2ETestSuite) TestComplianceExportDownloadCmdE2E() {
cmd := makeCmd()
cmd.Flags().Int("num-retries", 0, "")
err = complianceExportDownloadCmdF(s.th.Client, cmd, []string{job.Id})
s.Require().EqualError(err, "failed to download compliance export file: You do not have the appropriate permissions.")
s.Require().EqualError(err, "failed to download compliance export after 0 retries: You do not have the appropriate permissions.")
s.Require().Empty(printer.GetLines())
s.Require().Empty(printer.GetErrorLines())
})
@@ -349,7 +349,7 @@ func (s *MmctlE2ETestSuite) TestComplianceExportDownloadCmdE2E() {
cmd := makeCmd()
cmd.Flags().Int("num-retries", 0, "")
err := complianceExportDownloadCmdF(c, cmd, []string{"non-existent-job-id"})
s.Require().EqualError(err, "failed to download compliance export file: Sorry, we could not find the page., There doesn't appear to be an api call for the url='/api/v4/jobs/non-existent-job-id/download'. Typo? are you missing a team_id or user_id as part of the url?")
s.Require().EqualError(err, "failed to download compliance export after 0 retries: Sorry, we could not find the page., There doesn't appear to be an api call for the url='/api/v4/jobs/non-existent-job-id/download'. Typo? are you missing a team_id or user_id as part of the url?")
s.Require().Empty(printer.GetLines())
s.Require().Empty(printer.GetErrorLines())
})
-9
View File
@@ -95,20 +95,11 @@ var ExportJobCancelCmd = &cobra.Command{
}
func init() {
ExportCreateCmd.Flags().Bool("attachments", false, "Set to true to include file attachments in the export file.")
_ = ExportCreateCmd.Flags().MarkHidden("attachments")
_ = ExportCreateCmd.Flags().MarkDeprecated("attachments", "the tool now includes attachments by default. The flag will be removed in a future version.")
ExportCreateCmd.Flags().Bool("no-attachments", false, "Exclude file attachments from the export file.")
ExportCreateCmd.Flags().Bool("include-archived-channels", false, "Include archived channels in the export file.")
ExportCreateCmd.Flags().Bool("include-profile-pictures", false, "Include profile pictures in the export file.")
ExportCreateCmd.Flags().Bool("no-roles-and-schemes", false, "Exclude roles and custom permission schemes from the export file.")
ExportDownloadCmd.Flags().Bool("resume", false, "Set to true to resume an export download.")
_ = ExportDownloadCmd.Flags().MarkHidden("resume")
// Intentionally the message does not start with a capital letter because
// cobra prepends "Flag --resume has been deprecated,"
_ = ExportDownloadCmd.Flags().MarkDeprecated("resume", "the tool now resumes a download automatically. The flag will be removed in a future version.")
ExportDownloadCmd.Flags().Int("num-retries", 5, "Number of retries to do to resume a download.")
ExportJobListCmd.Flags().Int("page", 0, "Page number to fetch for the list of export jobs")
-11
View File
@@ -40,16 +40,6 @@ var RemovePermissionsCmd = &cobra.Command{
RunE: withClient(removePermissionsCmdF),
}
var ShowRoleCmd = &cobra.Command{
Use: "show <role_name>",
Deprecated: "please use \"mmctl permissions role show\" instead",
Short: "Show the role information",
Long: "Show all the information about a role.",
Example: ` permissions show system_user`,
Args: cobra.ExactArgs(1),
RunE: withClient(showRoleCmdF),
}
var ResetCmd = &cobra.Command{
Use: "reset <role_name>",
Short: "Reset default permissions for role (EE Only)",
@@ -64,7 +54,6 @@ func init() {
PermissionsCmd.AddCommand(
AddPermissionsCmd,
RemovePermissionsCmd,
ShowRoleCmd,
ResetCmd,
)
-3
View File
@@ -27,9 +27,6 @@ func Run(args []string) error {
RootCmd.PersistentFlags().String("config", filepath.Join(xdgConfigHomeVar, configParent, configFileName), "path to the configuration file")
_ = viper.BindPFlag("config", RootCmd.PersistentFlags().Lookup("config"))
RootCmd.PersistentFlags().String("config-path", xdgConfigHomeVar, "path to the configuration directory.")
_ = viper.BindPFlag("config-path", RootCmd.PersistentFlags().Lookup("config-path"))
_ = RootCmd.PersistentFlags().MarkHidden("config-path")
RootCmd.PersistentFlags().Bool("suppress-warnings", false, "disables printing warning messages")
_ = viper.BindPFlag("suppress-warnings", RootCmd.PersistentFlags().Lookup("suppress-warnings"))
RootCmd.PersistentFlags().String("format", "plain", "the format of the command output [plain, json]")
+4 -15
View File
@@ -100,8 +100,6 @@ var ModifyTeamsCmd = &cobra.Command{
func init() {
TeamCreateCmd.Flags().String("name", "", "Team Name")
TeamCreateCmd.Flags().String("display-name", "", "Team Display Name")
TeamCreateCmd.Flags().String("display_name", "", "")
_ = TeamCreateCmd.Flags().MarkDeprecated("display_name", "please use display-name instead")
TeamCreateCmd.Flags().Bool("private", false, "Create a private team.")
TeamCreateCmd.Flags().String("email", "", "Administrator Email (anyone with this email is automatically a team admin)")
@@ -113,9 +111,7 @@ func init() {
// Add flag declaration for RenameTeam
RenameTeamCmd.Flags().String("display-name", "", "Team Display Name")
// _ = RenameTeamCmd.MarkFlagRequired("display-name") // Uncomment this after fully deprecation of display_name
RenameTeamCmd.Flags().String("display_name", "", "")
_ = RenameTeamCmd.Flags().MarkDeprecated("display_name", "please use display-name instead")
_ = RenameTeamCmd.MarkFlagRequired("display-name")
TeamCmd.AddCommand(
TeamCreateCmd,
@@ -140,10 +136,7 @@ func createTeamCmdF(c client.Client, cmd *cobra.Command, args []string) error {
}
displayname, errdn := cmd.Flags().GetString("display-name")
if errdn != nil || displayname == "" {
displayname, errdn = cmd.Flags().GetString("display_name")
if errdn != nil || displayname == "" {
return errors.New("display Name is required")
}
return errors.New("display-name is required")
}
email, _ := cmd.Flags().GetString("email")
useprivate, _ := cmd.Flags().GetBool("private")
@@ -275,13 +268,9 @@ func removeDuplicatesAndSortTeams(teams []*model.Team) []*model.Team {
func renameTeamCmdF(c client.Client, cmd *cobra.Command, args []string) error {
oldTeamName := args[0]
newDisplayName, _ := cmd.Flags().GetString("display_name")
newDisplayName, _ := cmd.Flags().GetString("display-name")
if newDisplayName == "" {
newDisplayName, _ = cmd.Flags().GetString("display-name")
}
if newDisplayName == "" {
return errors.New("display name is required")
return errors.New("display-name is required")
}
team := getTeamFromTeamArg(c, oldTeamName)
+1 -1
View File
@@ -233,7 +233,7 @@ func (s *MmctlE2ETestSuite) TestTeamCreateCmdF() {
cmd.Flags().String("name", model.NewId(), "")
err := createTeamCmdF(c, cmd, []string{})
s.EqualError(err, "display Name is required")
s.EqualError(err, "display-name is required")
s.Require().Empty(printer.GetLines())
})
+1 -1
View File
@@ -37,7 +37,7 @@ func (s *MmctlUnitTestSuite) TestCreateTeamCmd() {
cmd.Flags().String("name", mockTeamName, "")
err := createTeamCmdF(s.client, cmd, []string{})
s.Require().Equal(err, errors.New("display Name is required"))
s.Require().Equal(err, errors.New("display-name is required"))
s.Require().Len(printer.GetLines(), 0)
})
-15
View File
@@ -335,12 +335,8 @@ func init() {
UserCreateCmd.Flags().String("lastname", "", "Optional. The last name for the new user account")
UserCreateCmd.Flags().String("locale", "", "Optional. The locale (ex: en, fr) for the new user account")
UserCreateCmd.Flags().Bool("system-admin", false, "Optional. If supplied, the new user will be a system administrator. Defaults to false")
UserCreateCmd.Flags().Bool("system_admin", false, "")
_ = UserCreateCmd.Flags().MarkDeprecated("system_admin", "please use system-admin instead")
UserCreateCmd.Flags().Bool("guest", false, "Optional. If supplied, the new user will be a guest. Defaults to false")
UserCreateCmd.Flags().Bool("email-verified", false, "Optional. If supplied, the new user will have the email verified. Defaults to false")
UserCreateCmd.Flags().Bool("email_verified", false, "")
_ = UserCreateCmd.Flags().MarkDeprecated("email_verified", "please use email-verified instead")
UserCreateCmd.Flags().Bool("disable-welcome-email", false, "Optional. If supplied, the new user will not receive a welcome email. Defaults to false")
DeleteUsersCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed")
@@ -362,8 +358,6 @@ func init() {
UserConvertCmd.Flags().String("lastname", "", "The last name for the converted user account. Required when the \"bot\" flag is set")
UserConvertCmd.Flags().String("locale", "", "The locale (ex: en, fr) for converted new user account. Required when the \"bot\" flag is set")
UserConvertCmd.Flags().Bool("system-admin", false, "If supplied, the converted user will be a system administrator. Defaults to false. Required when the \"bot\" flag is set")
UserConvertCmd.Flags().Bool("system_admin", false, "")
_ = UserConvertCmd.Flags().MarkDeprecated("system_admin", "please use system-admin instead")
ChangePasswordUserCmd.Flags().StringP("current", "c", "", "The current password of the user. Use only if changing your own password")
ChangePasswordUserCmd.Flags().StringP("password", "p", "", "The new password for the user")
@@ -507,14 +501,8 @@ func userCreateCmdF(c client.Client, cmd *cobra.Command, args []string) error {
lastname, _ := cmd.Flags().GetString("lastname")
locale, _ := cmd.Flags().GetString("locale")
systemAdmin, _ := cmd.Flags().GetBool("system-admin")
if !systemAdmin {
systemAdmin, _ = cmd.Flags().GetBool("system_admin")
}
guest, _ := cmd.Flags().GetBool("guest")
emailVerified, _ := cmd.Flags().GetBool("email-verified")
if !emailVerified {
emailVerified, _ = cmd.Flags().GetBool("email_verified")
}
disableWelcomeEmail, _ := cmd.Flags().GetBool("disable-welcome-email")
user := &model.User{
@@ -1009,9 +997,6 @@ func convertBotToUser(c client.Client, cmd *cobra.Command, userArgs []string) er
}
systemAdmin, _ := cmd.Flags().GetBool("system-admin")
if !systemAdmin {
systemAdmin, _ = cmd.Flags().GetBool("system_admin")
}
user, _, err = c.ConvertBotToUser(context.TODO(), user.Id, up, systemAdmin)
if err != nil {