[MM-63556] mmctl: Add compliance export download cmd (#30576)

* add mmctl compliance export download command and tests

- Introduced `ComplianceExportDownloadCmd` to facilitate downloading compliance export files.
- Implemented the `DownloadComplianceExport` method in the Client interface for handling file downloads.
- Added unit tests for the download command, covering successful downloads, error handling for non-existent jobs, and retries on failure.
- Included end-to-end tests to validate the command's functionality.
- Updated documentation to include usage examples and options for the new command.

* don't know why this was left out

* PR comments

* adjust test for new retry logic

* refactored download fn for compliance_export and export

* fix test due to fixed logic

* docs
Этот коммит содержится в:
Christopher Poile
2025-06-24 16:27:54 -04:00
коммит произвёл GitHub
родитель 60a747f975
Коммит b33a7e362f
12 изменённых файлов: 548 добавлений и 22 удалений

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

@@ -6,8 +6,10 @@ package commands
import (
"context"
"fmt"
"os"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/client"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
"github.com/spf13/cobra"
)
@@ -40,15 +42,26 @@ var ComplianceExportCancelCmd = &cobra.Command{
RunE: withClient(complianceExportCancelCmdF),
}
var ComplianceExportDownloadCmd = &cobra.Command{
Use: "download [complianceExportJobID] [output filepath (optional)]",
Example: " compliance_export download o98rj3ur83dp5dppfyk5yk6osy",
Short: "Download compliance export file",
Args: cobra.MinimumNArgs(1),
RunE: withClient(complianceExportDownloadCmdF),
}
func init() {
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().Bool("all", false, "Fetch all compliance export jobs. --page flag will be ignored if provided")
ComplianceExportDownloadCmd.Flags().Int("num-retries", 5, "Number of retries if the download fails")
ComplianceExportCmd.AddCommand(
ComplianceExportListCmd,
ComplianceExportShowCmd,
ComplianceExportCancelCmd,
ComplianceExportDownloadCmd,
)
RootCmd.AddCommand(ComplianceExportCmd)
}
@@ -75,3 +88,41 @@ func complianceExportCancelCmdF(c client.Client, command *cobra.Command, args []
return nil
}
func complianceExportDownloadCmdF(c client.Client, command *cobra.Command, args []string) error {
jobID := args[0]
var path string
if len(args) > 1 {
path = args[1]
} else {
path = jobID + ".zip"
}
retries, _ := command.Flags().GetInt("num-retries")
downloadFn := func(outFile *os.File) (string, error) {
return c.DownloadComplianceExport(context.TODO(), jobID, outFile)
}
suggestedFilename, err := downloadFile(path, downloadFn, retries, "compliance export")
if err != nil {
return err
}
// If we didn't provide a path and got a suggested filename, rename the file
if len(args) == 1 && suggestedFilename != "" && suggestedFilename != path {
// If the suggested name already exists, don't overwrite
if _, err := os.Stat(suggestedFilename); err == nil {
printer.PrintWarning(fmt.Sprintf("File with the server's suggested name %q already exists, keeping %q", suggestedFilename, path))
} else {
if err := os.Rename(path, suggestedFilename); err != nil {
printer.PrintWarning(fmt.Sprintf("Could not rename file to the server's suggested name %q: %v", suggestedFilename, err))
} else {
path = suggestedFilename
}
}
}
printer.Print(fmt.Sprintf("Compliance export file downloaded to %q", path))
return nil
}