Skip to content

Commit

Permalink
Add autocompletion to the slash command (#161)
Browse files Browse the repository at this point in the history
* feat: Add comprehensive autocompletion for cloud slash commands

* refactor: Move all flags to optional arguments in autocompletion

* refactor: Replace Optional: true with Required: false in AutocompleteArg

* refactor: Update test-data flag from Optional to Required: false

* refactor: Replace Name field with Type and Data in AutocompleteArg

* feat: Add affinity argument to create command autocomplete

* feat: Add database argument to create command autocomplete

* feat: Add --env argument to create command autocomplete

* feat: Add filestore argument to create command autocomplete

* feat: Add --image argument to create command autocomplete

* feat: Add --size argument to create command autocomplete

* feat: Add version argument to create command autocomplete

* feat: Add clear-env argument to update command autocomplete

* feat: Add --env argument to update command autocomplete

* feat: Add --image argument to update command autocomplete

* docs: Update license argument help text in update command autocomplete

* feat: Add --shared-installation argument to update command autocomplete

* feat: Add --size argument to update command autocomplete

* docs: Update version argument help text with example

* docs: Update help text for --test-data argument in create command

* docs: Update license argument help text in create command autocomplete

* feat: Update help text for --allow-updates in share command

* feat: Add TextType validation for affinity command argument

* feat: Add TextType autocomplete for create command flags

* feat: Add mmcli subcommand for running Mattermost CLI commands

* feat: Add mmctl subcommand to support running mmctl commands on installations

* feat: Update import subcommand autocomplete with proper type and data fields

* refactor: Remove RoleID from cloud command autocomplete configuration

* feat: Add configurable autocompletion for slash command

* feat: Add command autocompletion configuration option to plugin

* fix: Use p.getCommand() instead of undefined getCommand()

* Fixing linter errors
  • Loading branch information
jespino authored Nov 25, 2024
1 parent 63dd16a commit 0352aff
Show file tree
Hide file tree
Showing 4 changed files with 332 additions and 5 deletions.
7 changes: 7 additions & 0 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@
"value": "minio-operator"
}
]
},
{
"key": "EnableCommandAutocompletion",
"display_name": "Enable Command Autocompletion",
"type": "bool",
"help_text": "Enable or disable autocompletion for the /cloud slash command",
"default": true
}
]
}
Expand Down
325 changes: 321 additions & 4 deletions server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,332 @@ info
))
}

func getCommand() *model.Command {
func (p *Plugin) getCommand() *model.Command {
return &model.Command{
Trigger: "cloud",
DisplayName: "Mattermost Private Cloud",
Description: "This command allows spinning up and down Mattermost installations using Mattermost Private Cloud.",
AutoComplete: false,
AutoCompleteDesc: "Available commands: create, list, update, mmcli, mmctl, delete",
AutoComplete: p.getConfiguration().EnableCommandAutocompletion,
AutoCompleteDesc: "Available commands: create, list, update, mmcli, mmctl, delete, share, unshare, restart, hibernate, wake-up, info, import",
AutoCompleteHint: "[command]",
AutocompleteData: &model.AutocompleteData{
Trigger: "cloud",
SubCommands: []*model.AutocompleteData{
{
Trigger: "create",
HelpText: "Creates a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation",
Required: true,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "license",
},
Name: "license",
HelpText: "The Mattermost license to use. Can be 'enterprise', 'professional', 'e20', 'e10', or 'te' (default \"enterprise\")",
Required: false,
},
{
Name: "test-data",
HelpText: "Set to pre-load the server with test data",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "affinity",
Pattern: "^(isolated|multitenant)$",
},
Name: "affinity",
HelpText: "Whether the installation is isolated in it's own cluster or shares ones. Can be 'isolated' or 'multitenant' (default \"multitenant\")",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "database",
},
Name: "database",
HelpText: "Specify the backing database. Can be 'aws-multitenant-rds-postgres-pgbouncer' (RDS Postgres with pgbouncer proxy connections), 'aws-rds' (RDS MySQL). (default \"aws-multitenant-rds-postgres-pgbouncer\")",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "env",
},
Name: "env",
HelpText: "Environment variables in form: ENV1=test,ENV2=test",
Required: false,
},
{
Name: "image",
HelpText: "Docker image repository, can be mattermost/mattermost-enterprise-edition, mattermost/mm-ee-cloud, mattermost/mm-te, mattermost/mattermost-team-edition, mattermostdevelopment/mm-ee-test, mattermostdevelopment/mm-te-test, mattermostdevelopment/mattermost-enterprise-edition, mattermostdevelopment/mattermost-team-edition",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "filestore",
},
Name: "filestore",
HelpText: "Specify the backing file store. Can be 'bifrost' (S3 Shared Bucket), 'aws-multitenant-s3' (S3 Shared Bucket), 'aws-s3' (S3 Bucket). (default \"bifrost\")",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "image",
},
Name: "image",
HelpText: "Docker image repository. Can be mattermost/mattermost-enterprise-edition, mattermost/mm-ee-cloud, mattermost/mm-te, mattermost/mattermost-team-edition, mattermostdevelopment/mm-ee-test, mattermostdevelopment/mm-te-test, mattermostdevelopment/mattermost-enterprise-edition, mattermostdevelopment/mattermost-team-edition (default \"mattermost/mattermost-enterprise-edition\")",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "size",
},
Name: "size",
HelpText: "Size of the Mattermost installation e.g. 'miniSingleton' or 'miniHA' (default \"miniSingleton\")",
Required: false,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "version",
},
Name: "version",
HelpText: "Mattermost version to run, e.g. '9.1.0' (default \"latest\")",
Required: false,
},
},
},
{
Trigger: "list",
HelpText: "Lists your Mattermost installations",
Arguments: []*model.AutocompleteArg{
{
Name: "shared-installations",
HelpText: "Lists shared installations instead of personal ones",
Required: false,
},
},
},
{
Trigger: "update",
HelpText: "Update a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to update",
Required: true,
},
{
Name: "version",
HelpText: "Mattermost version to run, e.g. '9.1.0'",
Required: false,
},
{
Name: "license",
HelpText: "The enterprise license to use. Can be 'enterprise', 'professional', 'e20', 'e10', or 'te'",
Required: false,
},
{
Name: "clear-env",
HelpText: "List of custom environment variables to erase, for example: ENV1,ENV2",
Required: false,
},
{
Name: "env",
HelpText: "Environment variables in form: ENV1=test,ENV2=test",
Required: false,
},
{
Name: "shared-installation",
HelpText: "Set this to true when attempting to update a shared installation",
Required: false,
},
{
Name: "size",
HelpText: "Size of the Mattermost installation e.g. 'miniSingleton' or 'miniHA'",
Required: false,
},
},
},
{
Trigger: "share",
HelpText: "Share a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to share",
Required: true,
},
{
Name: "allow-updates",
HelpText: "Allow other plugin users to update the installation configuration",
Required: false,
},
},
},
{
Trigger: "unshare",
HelpText: "Remove sharing from an installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to unshare",
Required: true,
},
},
},
{
Trigger: "restart",
HelpText: "Restart a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to restart",
Required: true,
},
},
},
{
Trigger: "hibernate",
HelpText: "Hibernate a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to hibernate",
Required: true,
},
},
},
{
Trigger: "wake-up",
HelpText: "Wake up a hibernated installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to wake up",
Required: true,
},
},
},
{
Trigger: "delete",
HelpText: "Delete a Mattermost installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to delete",
Required: true,
},
},
},
{
Trigger: "info",
HelpText: "Show cloud plugin information",
},
{
Trigger: "import",
HelpText: "Import an existing installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "DNS",
},
HelpText: "DNS value of the installation to import",
Required: true,
},
},
},
{
Trigger: "mmcli",
HelpText: "Runs Mattermost CLI commands on an installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to run CLI commands on",
Required: true,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "mattermost-subcommand",
},
HelpText: "The Mattermost CLI subcommand to run",
Required: true,
},
},
},
{
Trigger: "mmctl",
HelpText: "Runs mmctl commands on an installation",
Arguments: []*model.AutocompleteArg{
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "name",
Pattern: "^[a-zA-Z0-9-]+$",
},
HelpText: "Name of the installation to run mmctl commands on",
Required: true,
},
{
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{
Hint: "mmctl-subcommand",
},
HelpText: "The mmctl subcommand to run",
Required: true,
},
},
},
},
},
}
}

Expand Down Expand Up @@ -155,7 +473,6 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
}

resp, isUserError, err := handler(stringArgs[2:], args)

if err != nil {
if isUserError {
return getCommandResponse(model.CommandResponseTypeEphemeral, fmt.Sprintf("__Error: %s__\n\nRun `/cloud help` for usage instructions.", err.Error()), args), nil
Expand Down
3 changes: 3 additions & 0 deletions server/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type configuration struct {

DefaultDatabase string
DefaultFilestore string

// EnableCommandAutocompletion determines if the slash command should support autocompletion
EnableCommandAutocompletion bool
}

// ConfigResponse is a struct representing a sanitized configuration object, intended to be passed to the front-end for usage
Expand Down
2 changes: 1 addition & 1 deletion server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,5 @@ func (p *Plugin) OnActivate() error {

p.setCloudClient()
p.dockerClient = NewDockerClient()
return p.API.RegisterCommand(getCommand())
return p.API.RegisterCommand(p.getCommand())
}

0 comments on commit 0352aff

Please sign in to comment.