[MM-63555] mmctl: Add compliance export show and cancel cmds (#30569)
* add compliance export cancel command and tests - Introduced `ComplianceExportCancelCmd` to allow cancellation of compliance export jobs. - Implemented unit tests for the cancellation command, covering successful cancellation, error handling for non-existent jobs, and cancellation in non-cancellable states. - Added end-to-end tests to validate the command's functionality in the E2E test suite. * mmctl docs * clean up example text; remove unneeded getJob * fix tests * fix tests, again. * prefer hyphen for command naming * update docs
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
9399398e04
Коммит
e60f878090
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var ComplianceExportCmd = &cobra.Command{
|
var ComplianceExportCmd = &cobra.Command{
|
||||||
Use: "compliance_export",
|
Use: "compliance-export",
|
||||||
Short: "Management of compliance exports",
|
Short: "Management of compliance exports",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,12 +26,20 @@ var ComplianceExportListCmd = &cobra.Command{
|
|||||||
|
|
||||||
var ComplianceExportShowCmd = &cobra.Command{
|
var ComplianceExportShowCmd = &cobra.Command{
|
||||||
Use: "show [complianceExportJobID]",
|
Use: "show [complianceExportJobID]",
|
||||||
Example: " compliance_export show o98rj3ur83dp5dppfyk5yk6osy",
|
Example: "compliance-export show o98rj3ur83dp5dppfyk5yk6osy",
|
||||||
Short: "Show compliance export job",
|
Short: "Show compliance export job",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: withClient(complianceExportShowCmdF),
|
RunE: withClient(complianceExportShowCmdF),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ComplianceExportCancelCmd = &cobra.Command{
|
||||||
|
Use: "cancel [complianceExportJobID]",
|
||||||
|
Example: "compliance-export cancel o98rj3ur83dp5dppfyk5yk6osy",
|
||||||
|
Short: "Cancel compliance export job",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: withClient(complianceExportCancelCmdF),
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ComplianceExportListCmd.Flags().Int("page", 0, "Page number to fetch for the list of compliance export jobs")
|
ComplianceExportListCmd.Flags().Int("page", 0, "Page number to fetch for the list of compliance export jobs")
|
||||||
ComplianceExportListCmd.Flags().Int("per-page", DefaultPageSize, "Number of compliance export jobs to be fetched")
|
ComplianceExportListCmd.Flags().Int("per-page", DefaultPageSize, "Number of compliance export jobs to be fetched")
|
||||||
@@ -40,6 +48,7 @@ func init() {
|
|||||||
ComplianceExportCmd.AddCommand(
|
ComplianceExportCmd.AddCommand(
|
||||||
ComplianceExportListCmd,
|
ComplianceExportListCmd,
|
||||||
ComplianceExportShowCmd,
|
ComplianceExportShowCmd,
|
||||||
|
ComplianceExportCancelCmd,
|
||||||
)
|
)
|
||||||
RootCmd.AddCommand(ComplianceExportCmd)
|
RootCmd.AddCommand(ComplianceExportCmd)
|
||||||
}
|
}
|
||||||
@@ -58,3 +67,11 @@ func complianceExportShowCmdF(c client.Client, command *cobra.Command, args []st
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func complianceExportCancelCmdF(c client.Client, command *cobra.Command, args []string) error {
|
||||||
|
if _, err := c.CancelJob(context.TODO(), args[0]); err != nil {
|
||||||
|
return fmt.Errorf("failed to cancel compliance export job: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -198,3 +198,106 @@ func (s *MmctlE2ETestSuite) TestComplianceExportShowCmdE2E() {
|
|||||||
s.Require().Equal(job.Id, printer.GetLines()[0].(*model.Job).Id)
|
s.Require().Equal(job.Id, printer.GetLines()[0].(*model.Job).Id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MmctlE2ETestSuite) TestComplianceExportCancelCmdE2E() {
|
||||||
|
s.SetupMessageExportTestHelper()
|
||||||
|
|
||||||
|
s.Run("no permissions", func() {
|
||||||
|
printer.Clean()
|
||||||
|
|
||||||
|
now := model.GetMillis()
|
||||||
|
// Create a job
|
||||||
|
job, _, err := s.th.SystemAdminClient.CreateJob(context.Background(), &model.Job{
|
||||||
|
Id: st.NewTestID(),
|
||||||
|
CreateAt: now - 1000,
|
||||||
|
Status: model.JobStatusInProgress,
|
||||||
|
Type: model.JobTypeMessageExport,
|
||||||
|
StartAt: now - 1000,
|
||||||
|
LastActivityAt: now - 1000,
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
defer func() {
|
||||||
|
// Ensure job is deleted from the database
|
||||||
|
var result string
|
||||||
|
result, err = s.th.App.Srv().Store().Job().Delete(job.Id)
|
||||||
|
s.Require().NoError(err, "Failed to delete job (result: %v)", result)
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd := makeCmd()
|
||||||
|
err = complianceExportCancelCmdF(s.th.Client, cmd, []string{job.Id})
|
||||||
|
s.Require().EqualError(err, "failed to get compliance export job: You do not have the appropriate permissions.")
|
||||||
|
s.Require().Empty(printer.GetLines())
|
||||||
|
s.Require().Empty(printer.GetErrorLines())
|
||||||
|
})
|
||||||
|
|
||||||
|
s.RunForSystemAdminAndLocal("Cancel non-existent job", func(c client.Client) {
|
||||||
|
printer.Clean()
|
||||||
|
|
||||||
|
cmd := makeCmd()
|
||||||
|
err := complianceExportCancelCmdF(c, cmd, []string{"non-existent-job-id"})
|
||||||
|
s.Require().EqualError(err, "failed to get compliance export job: 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'. 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())
|
||||||
|
})
|
||||||
|
|
||||||
|
s.RunForSystemAdminAndLocal("Cancel existing job", func(c client.Client) {
|
||||||
|
now := model.GetMillis()
|
||||||
|
// Create a job
|
||||||
|
job, _, err := s.th.SystemAdminClient.CreateJob(context.Background(), &model.Job{
|
||||||
|
Id: st.NewTestID(),
|
||||||
|
CreateAt: now - 1000,
|
||||||
|
Status: model.JobStatusInProgress,
|
||||||
|
Type: model.JobTypeMessageExport,
|
||||||
|
StartAt: now - 1000,
|
||||||
|
LastActivityAt: now - 1000,
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
defer func() {
|
||||||
|
// Ensure job is deleted from the database
|
||||||
|
var result string
|
||||||
|
result, err = s.th.App.Srv().Store().Job().Delete(job.Id)
|
||||||
|
s.Require().NoError(err, "Failed to delete job (result: %v)", result)
|
||||||
|
}()
|
||||||
|
|
||||||
|
printer.Clean()
|
||||||
|
cmd := makeCmd()
|
||||||
|
err = complianceExportCancelCmdF(c, cmd, []string{job.Id})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Empty(printer.GetLines())
|
||||||
|
s.Require().Empty(printer.GetErrorLines())
|
||||||
|
|
||||||
|
// Verify job was cancelled
|
||||||
|
job, _, err = s.th.SystemAdminClient.GetJob(context.Background(), job.Id)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(model.JobStatusCanceled, job.Status)
|
||||||
|
})
|
||||||
|
|
||||||
|
s.RunForSystemAdminAndLocal("Error cancelling job in non-cancellable state", func(c client.Client) {
|
||||||
|
now := model.GetMillis()
|
||||||
|
// Create a job
|
||||||
|
job, _, err := s.th.SystemAdminClient.CreateJob(context.Background(), &model.Job{
|
||||||
|
Id: st.NewTestID(),
|
||||||
|
CreateAt: now - 1000,
|
||||||
|
Status: model.JobStatusInProgress,
|
||||||
|
Type: model.JobTypeMessageExport,
|
||||||
|
StartAt: now - 1000,
|
||||||
|
LastActivityAt: now - 1000,
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
_, err = s.th.SystemAdminClient.UpdateJobStatus(context.Background(), job.Id, model.JobStatusCanceled, true)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
defer func() {
|
||||||
|
// Ensure job is deleted from the database
|
||||||
|
var result string
|
||||||
|
result, err = s.th.App.Srv().Store().Job().Delete(job.Id)
|
||||||
|
s.Require().NoError(err, "Failed to delete job (result: %v)", result)
|
||||||
|
}()
|
||||||
|
|
||||||
|
printer.Clean()
|
||||||
|
cmd := makeCmd()
|
||||||
|
err = complianceExportCancelCmdF(c, cmd, []string{job.Id})
|
||||||
|
s.Require().EqualError(err, "failed to cancel compliance export job: Could not request cancellation for job that is not in a cancelable state.")
|
||||||
|
s.Require().Empty(printer.GetLines())
|
||||||
|
s.Require().Empty(printer.GetErrorLines())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
func (s *MmctlUnitTestSuite) TestComplianceExportListCmdF() {
|
func (s *MmctlUnitTestSuite) TestComplianceExportListCmdF() {
|
||||||
s.Run("list default pagination", func() {
|
s.Run("list default pagination", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
printer.Clean()
|
printer.Clean()
|
||||||
var mockJobs []*model.Job
|
var mockJobs []*model.Job
|
||||||
|
|
||||||
@@ -115,6 +116,7 @@ func (s *MmctlUnitTestSuite) TestComplianceExportListCmdF() {
|
|||||||
|
|
||||||
func (s *MmctlUnitTestSuite) TestComplianceExportShowCmdF() {
|
func (s *MmctlUnitTestSuite) TestComplianceExportShowCmdF() {
|
||||||
s.Run("show job successfully", func() {
|
s.Run("show job successfully", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
printer.Clean()
|
printer.Clean()
|
||||||
mockJob := &model.Job{
|
mockJob := &model.Job{
|
||||||
Id: model.NewId(),
|
Id: model.NewId(),
|
||||||
@@ -137,6 +139,7 @@ func (s *MmctlUnitTestSuite) TestComplianceExportShowCmdF() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
s.Run("show job with error", func() {
|
s.Run("show job with error", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
printer.Clean()
|
printer.Clean()
|
||||||
mockError := &model.AppError{
|
mockError := &model.AppError{
|
||||||
Message: "failed to get job",
|
Message: "failed to get job",
|
||||||
@@ -157,6 +160,70 @@ func (s *MmctlUnitTestSuite) TestComplianceExportShowCmdF() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MmctlUnitTestSuite) TestComplianceExportCancelCmdF() {
|
||||||
|
s.Run("cancel job successfully", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
|
printer.Clean()
|
||||||
|
id := model.NewId()
|
||||||
|
|
||||||
|
s.client.
|
||||||
|
EXPECT().
|
||||||
|
CancelJob(context.TODO(), id).
|
||||||
|
Return(&model.Response{}, nil).
|
||||||
|
Times(1)
|
||||||
|
|
||||||
|
cmd := makeCmd()
|
||||||
|
err := complianceExportCancelCmdF(s.client, cmd, []string{id})
|
||||||
|
s.Require().Nil(err)
|
||||||
|
s.Len(printer.GetLines(), 0)
|
||||||
|
s.Len(printer.GetErrorLines(), 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
s.Run("cancel job with get error", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
|
printer.Clean()
|
||||||
|
mockError := &model.AppError{
|
||||||
|
Message: "failed to get job",
|
||||||
|
}
|
||||||
|
|
||||||
|
s.client.
|
||||||
|
EXPECT().
|
||||||
|
CancelJob(context.TODO(), "invalid-job-id").
|
||||||
|
Return(&model.Response{}, mockError).
|
||||||
|
Times(1)
|
||||||
|
|
||||||
|
cmd := makeCmd()
|
||||||
|
err := complianceExportCancelCmdF(s.client, cmd, []string{"invalid-job-id"})
|
||||||
|
s.Require().NotNil(err)
|
||||||
|
s.EqualError(err, "failed to cancel compliance export job: failed to get job")
|
||||||
|
s.Len(printer.GetLines(), 0)
|
||||||
|
s.Len(printer.GetErrorLines(), 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
s.Run("cancel job with cancel error", func() {
|
||||||
|
s.SetupTest() // Reset mocks before test
|
||||||
|
printer.Clean()
|
||||||
|
id := model.NewId()
|
||||||
|
|
||||||
|
mockError := &model.AppError{
|
||||||
|
Message: "failed to cancel job",
|
||||||
|
}
|
||||||
|
|
||||||
|
s.client.
|
||||||
|
EXPECT().
|
||||||
|
CancelJob(context.TODO(), id).
|
||||||
|
Return(&model.Response{}, mockError).
|
||||||
|
Times(1)
|
||||||
|
|
||||||
|
cmd := makeCmd()
|
||||||
|
err := complianceExportCancelCmdF(s.client, cmd, []string{id})
|
||||||
|
s.Require().NotNil(err)
|
||||||
|
s.EqualError(err, "failed to cancel compliance export job: failed to cancel job")
|
||||||
|
s.Len(printer.GetLines(), 0)
|
||||||
|
s.Len(printer.GetErrorLines(), 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func makeCmd() *cobra.Command {
|
func makeCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{}
|
cmd := &cobra.Command{}
|
||||||
cmd.Flags().Int("page", 0, "")
|
cmd.Flags().Int("page", 0, "")
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ SEE ALSO
|
|||||||
* `mmctl channel <mmctl_channel.rst>`_ - Management of channels
|
* `mmctl channel <mmctl_channel.rst>`_ - Management of channels
|
||||||
* `mmctl command <mmctl_command.rst>`_ - Management of slash commands
|
* `mmctl command <mmctl_command.rst>`_ - Management of slash commands
|
||||||
* `mmctl completion <mmctl_completion.rst>`_ - Generates autocompletion scripts for bash and zsh
|
* `mmctl completion <mmctl_completion.rst>`_ - Generates autocompletion scripts for bash and zsh
|
||||||
* `mmctl compliance_export <mmctl_compliance_export.rst>`_ - Management of compliance exports
|
* `mmctl compliance-export <mmctl_compliance-export.rst>`_ - Management of compliance exports
|
||||||
* `mmctl config <mmctl_config.rst>`_ - Configuration
|
* `mmctl config <mmctl_config.rst>`_ - Configuration
|
||||||
* `mmctl docs <mmctl_docs.rst>`_ - Generates mmctl documentation
|
* `mmctl docs <mmctl_docs.rst>`_ - Generates mmctl documentation
|
||||||
* `mmctl export <mmctl_export.rst>`_ - Management of exports
|
* `mmctl export <mmctl_export.rst>`_ - Management of exports
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.. _mmctl_compliance_export:
|
.. _mmctl_compliance-export:
|
||||||
|
|
||||||
mmctl compliance_export
|
mmctl compliance-export
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Management of compliance exports
|
Management of compliance exports
|
||||||
@@ -16,7 +16,7 @@ Options
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
-h, --help help for compliance_export
|
-h, --help help for compliance-export
|
||||||
|
|
||||||
Options inherited from parent commands
|
Options inherited from parent commands
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -37,6 +37,7 @@ SEE ALSO
|
|||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
* `mmctl <mmctl.rst>`_ - Remote client for the Open Source, self-hosted Slack-alternative
|
* `mmctl <mmctl.rst>`_ - Remote client for the Open Source, self-hosted Slack-alternative
|
||||||
* `mmctl compliance_export list <mmctl_compliance_export_list.rst>`_ - List compliance export jobs, sorted by creation date descending (newest first)
|
* `mmctl compliance-export cancel <mmctl_compliance-export_cancel.rst>`_ - Cancel compliance export job
|
||||||
* `mmctl compliance_export show <mmctl_compliance_export_show.rst>`_ - Show compliance export job
|
* `mmctl compliance-export list <mmctl_compliance-export_list.rst>`_ - List compliance export jobs, sorted by creation date descending (newest first)
|
||||||
|
* `mmctl compliance-export show <mmctl_compliance-export_show.rst>`_ - Show compliance export job
|
||||||
|
|
||||||
51
server/cmd/mmctl/docs/mmctl_compliance-export_cancel.rst
Обычный файл
51
server/cmd/mmctl/docs/mmctl_compliance-export_cancel.rst
Обычный файл
@@ -0,0 +1,51 @@
|
|||||||
|
.. _mmctl_compliance-export_cancel:
|
||||||
|
|
||||||
|
mmctl compliance-export cancel
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Cancel compliance export job
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
Cancel compliance export job
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
mmctl compliance-export cancel [complianceExportJobID] [flags]
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
compliance-export cancel o98rj3ur83dp5dppfyk5yk6osy
|
||||||
|
|
||||||
|
Options
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
-h, --help help for cancel
|
||||||
|
|
||||||
|
Options inherited from parent commands
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
--config string path to the configuration file (default "$XDG_CONFIG_HOME/mmctl/config")
|
||||||
|
--disable-pager disables paged output
|
||||||
|
--insecure-sha1-intermediate allows to use insecure TLS protocols, such as SHA-1
|
||||||
|
--insecure-tls-version allows to use TLS versions 1.0 and 1.1
|
||||||
|
--json the output format will be in json format
|
||||||
|
--local allows communicating with the server through a unix socket
|
||||||
|
--quiet prevent mmctl to generate output for the commands
|
||||||
|
--strict will only run commands if the mmctl version matches the server one
|
||||||
|
--suppress-warnings disables printing warning messages
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
* `mmctl compliance-export <mmctl_compliance-export.rst>`_ - Management of compliance exports
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
.. _mmctl_compliance_export_list:
|
.. _mmctl_compliance-export_list:
|
||||||
|
|
||||||
mmctl compliance_export list
|
mmctl compliance-export list
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
List compliance export jobs, sorted by creation date descending (newest first)
|
List compliance export jobs, sorted by creation date descending (newest first)
|
||||||
@@ -13,7 +13,7 @@ List compliance export jobs, sorted by creation date descending (newest first)
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
mmctl compliance_export list [flags]
|
mmctl compliance-export list [flags]
|
||||||
|
|
||||||
Options
|
Options
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
@@ -43,5 +43,5 @@ Options inherited from parent commands
|
|||||||
SEE ALSO
|
SEE ALSO
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
* `mmctl compliance_export <mmctl_compliance_export.rst>`_ - Management of compliance exports
|
* `mmctl compliance-export <mmctl_compliance-export.rst>`_ - Management of compliance exports
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
.. _mmctl_compliance_export_show:
|
.. _mmctl_compliance-export_show:
|
||||||
|
|
||||||
mmctl compliance_export show
|
mmctl compliance-export show
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Show compliance export job
|
Show compliance export job
|
||||||
@@ -13,14 +13,14 @@ Show compliance export job
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
mmctl compliance_export show [complianceExportJobID] [flags]
|
mmctl compliance-export show [complianceExportJobID] [flags]
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
compliance_export show o98rj3ur83dp5dppfyk5yk6osy
|
compliance-export show o98rj3ur83dp5dppfyk5yk6osy
|
||||||
|
|
||||||
Options
|
Options
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
@@ -47,5 +47,5 @@ Options inherited from parent commands
|
|||||||
SEE ALSO
|
SEE ALSO
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
* `mmctl compliance_export <mmctl_compliance_export.rst>`_ - Management of compliance exports
|
* `mmctl compliance-export <mmctl_compliance-export.rst>`_ - Management of compliance exports
|
||||||
|
|
||||||
Ссылка в новой задаче
Block a user