From bd76d2b1ae24d16a7acde40122587c933113674f Mon Sep 17 00:00:00 2001 From: Amber Xu Date: Tue, 2 Dec 2025 01:11:16 -0800 Subject: [PATCH 1/2] implement backup cmd for v4 --- cmd/backup.go | 253 ++++++++++++++++++++++++++++++----------- cmd/backup_v3_test.go | 145 +++++++++++++++++++++++ cmd/backup_v4_test.go | 145 +++++++++++++++++++++++ docs/fmeflow_backup.md | 5 +- 4 files changed, 479 insertions(+), 69 deletions(-) create mode 100644 cmd/backup_v3_test.go create mode 100644 cmd/backup_v4_test.go diff --git a/cmd/backup.go b/cmd/backup.go index 0ffb091..a08029e 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -12,8 +12,20 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/viper" ) +type backupDownloadV4 struct { + PackageName string `json:"packageName"` +} + +type backupResourceV4 struct { + ResourceName string `json:"resourceName"` + PackagePath string `json:"packagePath"` + SuccessTopic string `json:"successTopic"` + FailureTopic string `json:"failureTopic"` +} + type backupFlags struct { outputBackupFile string backupResourceName string @@ -22,12 +34,15 @@ type backupFlags struct { backupSuccessTopic string backupResource bool suppressFileRename bool + apiVersion apiVersionFlag } type BackupResource struct { Id int `json:"id"` } +var backupV4BuildThreshold = 25208 + // backupCmd represents the backup command func newBackupCmd() *cobra.Command { f := backupFlags{} @@ -52,9 +67,10 @@ func newBackupCmd() *cobra.Command { cmd.Flags().BoolVar(&f.backupResource, "resource", false, "Backup to a shared resource instead of downloading.") cmd.Flags().StringVar(&f.backupResourceName, "resource-name", "FME_SHAREDRESOURCE_BACKUP", "Shared Resource Name where the exported package is saved.") cmd.Flags().StringVar(&f.backupExportPackage, "export-package", "ServerConfigPackage.fsconfig", "Path and name of the export package.") - cmd.Flags().StringVar(&f.backupFailureTopic, "failure-topic", "", "Topic to notify on failure of the backup. Default is MIGRATION_ASYNC_JOB_FAILURE") - cmd.Flags().StringVar(&f.backupSuccessTopic, "success-topic", "", "Topic to notify on success of the backup. Default is MIGRATION_ASYNC_JOB_SUCCESS") + cmd.Flags().StringVar(&f.backupFailureTopic, "failure-topic", "", "Topic to notify on failure of the backup. In V3, default is MIGRATION_ASYNC_JOB_FAILURE") + cmd.Flags().StringVar(&f.backupSuccessTopic, "success-topic", "", "Topic to notify on success of the backup. In V3, default is MIGRATION_ASYNC_JOB_SUCCESS") cmd.Flags().BoolVar(&f.suppressFileRename, "suppress-file-rename", false, "Specify this flag to not add .fsconfig to the output file automatically") + cmd.Flags().Var(&f.apiVersion, "api-version", "The api version to use when contacting FME Server. Must be one of v3 or v4") cmd.MarkFlagsMutuallyExclusive("file", "resource") cmd.MarkFlagsMutuallyExclusive("file", "resource-name") cmd.MarkFlagsMutuallyExclusive("file", "export-package") @@ -77,91 +93,194 @@ func backupRun(f *backupFlags) func(cmd *cobra.Command, args []string) error { } } - if !f.backupResource { - - // add mandatory values - data := url.Values{ - "exportPackageName": {f.outputBackupFile}, + if f.apiVersion == "" { + if viper.GetInt("build") < backupV4BuildThreshold { + f.apiVersion = apiVersionFlagV3 + } else { + f.apiVersion = apiVersionFlagV4 } + } - request, err := buildFmeFlowRequest("/fmerest/v3/migration/backup/download", "POST", strings.NewReader(data.Encode())) - if err != nil { - return err - } + if f.apiVersion == apiVersionFlagV4 { - request.Header.Add("Content-Type", "application/x-www-form-urlencoded") - request.Header.Add("Accept", "application/octet-stream") + if !f.backupResource { + var backupRequest backupDownloadV4 + backupRequest.PackageName = f.outputBackupFile - fmt.Fprintln(cmd.OutOrStdout(), "Downloading backup file...") + requestBody, err := json.Marshal(backupRequest) + if err != nil { + return err + } - response, err := client.Do(&request) - if err != nil { - return err - } else if response.StatusCode != 200 { - return errors.New(response.Status) - } - defer response.Body.Close() + request, err := buildFmeFlowRequest("/fmeapiv4/migrations/backup/download", "POST", strings.NewReader(string(requestBody))) + if err != nil { + return err + } - // Create the output file - out, err := os.Create(f.outputBackupFile) - if err != nil { - return err - } - defer out.Close() + request.Header.Add("Content-Type", "application/json") - // use Copy so that it doesn't store the entire file in memory - _, err = io.Copy(out, response.Body) - if err != nil { - return err - } + fmt.Fprintln(cmd.OutOrStdout(), "Downloading backup file...") + response, err := client.Do(&request) + if err != nil { + return err + } else if response.StatusCode != 200 { + return errors.New(response.Status) + } + defer response.Body.Close() - fmt.Fprintln(cmd.OutOrStdout(), "FME Server backed up to "+f.outputBackupFile) - } else { - // backup to a resource - // add mandatory values - data := url.Values{ - "exportPackage": {f.backupExportPackage}, - "resourceName": {f.backupResourceName}, - } + // Create the output file + out, err := os.Create(f.outputBackupFile) + if err != nil { + return err + } + defer out.Close() - // add optional values - if f.backupSuccessTopic != "" { - data.Add("successTopic", f.backupSuccessTopic) - } - if f.backupFailureTopic != "" { - data.Add("failureTopic", f.backupFailureTopic) - } + // use Copy so that it doesn't store the entire file in memory + _, err = io.Copy(out, response.Body) + if err != nil { + return err + } - request, err := buildFmeFlowRequest("/fmerest/v3/migration/backup/resource", "POST", strings.NewReader(data.Encode())) - if err != nil { - return err - } + fmt.Fprintln(cmd.OutOrStdout(), "FME Server backed up to "+f.outputBackupFile) - request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + } else { + // backup to a resource + var backupRequest backupResourceV4 + backupRequest.PackagePath = f.backupExportPackage + backupRequest.ResourceName = f.backupResourceName + if f.backupSuccessTopic != "" { + backupRequest.SuccessTopic = f.backupSuccessTopic + } + if f.backupFailureTopic != "" { + backupRequest.FailureTopic = f.backupFailureTopic + } + requestBody, err := json.Marshal(backupRequest) + if err != nil { + return err + } + request, err := buildFmeFlowRequest("/fmeapiv4/migrations/backup/resource", "POST", strings.NewReader(string(requestBody))) + if err != nil { + return err + } - response, err := client.Do(&request) - if err != nil { - return err - } else if response.StatusCode != http.StatusAccepted { - return errors.New(response.Status) - } + request.Header.Add("Content-Type", "application/json") + + response, err := client.Do(&request) + if err != nil { + return err + } else if response.StatusCode != 202 && response.StatusCode != 200 { + if response.StatusCode == 401 { + return errors.New("failed to login") + } else { + return errors.New(response.Status) + } + } + responseData, err := io.ReadAll(response.Body) + if err != nil { + return err + } + + var result BackupResource + if err := json.Unmarshal(responseData, &result); err != nil { + return err + } else { + if !jsonOutput { + fmt.Fprintln(cmd.OutOrStdout(), "Backup task submitted with id: "+strconv.Itoa(result.Id)) + } else { + fmt.Fprintln(cmd.OutOrStdout(), string(responseData)) + } + } - responseData, err := io.ReadAll(response.Body) - if err != nil { - return err } - var result BackupResource - if err := json.Unmarshal(responseData, &result); err != nil { - return err + } else if f.apiVersion == apiVersionFlagV3 { + if !f.backupResource { + + // add mandatory values + data := url.Values{ + "exportPackageName": {f.outputBackupFile}, + } + + request, err := buildFmeFlowRequest("/fmerest/v3/migration/backup/download", "POST", strings.NewReader(data.Encode())) + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + request.Header.Add("Accept", "application/octet-stream") + + fmt.Fprintln(cmd.OutOrStdout(), "Downloading backup file...") + + response, err := client.Do(&request) + if err != nil { + return err + } else if response.StatusCode != 200 { + return errors.New(response.Status) + } + defer response.Body.Close() + + // Create the output file + out, err := os.Create(f.outputBackupFile) + if err != nil { + return err + } + defer out.Close() + + // use Copy so that it doesn't store the entire file in memory + _, err = io.Copy(out, response.Body) + if err != nil { + return err + } + + fmt.Fprintln(cmd.OutOrStdout(), "FME Server backed up to "+f.outputBackupFile) } else { - if !jsonOutput { - fmt.Fprintln(cmd.OutOrStdout(), "Backup task submitted with id: "+strconv.Itoa(result.Id)) + // backup to a resource + // add mandatory values + data := url.Values{ + "exportPackage": {f.backupExportPackage}, + "resourceName": {f.backupResourceName}, + } + + // add optional values + if f.backupSuccessTopic != "" { + data.Add("successTopic", f.backupSuccessTopic) + } + if f.backupFailureTopic != "" { + data.Add("failureTopic", f.backupFailureTopic) + } + + request, err := buildFmeFlowRequest("/fmerest/v3/migration/backup/resource", "POST", strings.NewReader(data.Encode())) + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + response, err := client.Do(&request) + if err != nil { + return err + } else if response.StatusCode != http.StatusAccepted { + return errors.New(response.Status) + } + + responseData, err := io.ReadAll(response.Body) + if err != nil { + return err + } + + var result BackupResource + if err := json.Unmarshal(responseData, &result); err != nil { + return err } else { - fmt.Fprintln(cmd.OutOrStdout(), string(responseData)) + if !jsonOutput { + fmt.Fprintln(cmd.OutOrStdout(), "Backup task submitted with id: "+strconv.Itoa(result.Id)) + } else { + fmt.Fprintln(cmd.OutOrStdout(), string(responseData)) + } } } } + return nil } } diff --git a/cmd/backup_v3_test.go b/cmd/backup_v3_test.go new file mode 100644 index 0000000..5afe6d0 --- /dev/null +++ b/cmd/backup_v3_test.go @@ -0,0 +1,145 @@ +package cmd + +import ( + "net/http" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBackupV3(t *testing.T) { + // standard responses for v3 and v4 + okResponseV3 := `Random file contents` + + // generate random file to back up to + f, err := os.CreateTemp("", "*fmeflow-backup.fsconfig") + require.NoError(t, err) + defer os.Remove(f.Name()) // clean up + + cases := []testCase{ + { + name: "unknown flag", + statusCode: http.StatusOK, + args: []string{"backup", "--badflag"}, + wantErrOutputRegex: "unknown flag: --badflag", + fmeflowBuild: 23166, + }, + { + name: "500 bad status code", + statusCode: http.StatusInternalServerError, + wantErrText: "500 Internal Server Error", + args: []string{"backup"}, + fmeflowBuild: 23166, + }, + { + name: "422 bad status code", + statusCode: http.StatusNotFound, + wantErrText: "404 Not Found", + args: []string{"backup"}, + fmeflowBuild: 23166, + }, + { + name: "backup to file", + statusCode: http.StatusOK, + args: []string{"backup", "--file", f.Name()}, + body: okResponseV3, + wantOutputRegex: "FME Server backed up to", + wantFileContents: fileContents{file: f.Name(), contents: okResponseV3}, + fmeflowBuild: 23166, + }, + { + name: "backup to shared resource", + statusCode: http.StatusAccepted, + args: []string{"backup", "--resource"}, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + wantFormParams: map[string]string{"resourceName": "FME_SHAREDRESOURCE_BACKUP"}, + fmeflowBuild: 23166, + }, + { + name: "export to specific file name", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--export-package", "TestPackageName.fsconfig"}, + wantFormParams: map[string]string{"exportPackage": "TestPackageName.fsconfig", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, + fmeflowBuild: 23166, + }, + { + name: "specify failure topic", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--failure-topic", "SAMPLE_TOPIC"}, + wantFormParams: map[string]string{"failureTopic": "SAMPLE_TOPIC", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, + fmeflowBuild: 23166, + }, + { + name: "specify success topic", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--success-topic", "SAMPLE_TOPIC"}, + wantFormParams: map[string]string{"successTopic": "SAMPLE_TOPIC", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, + fmeflowBuild: 23166, + }, + { + name: "don't allow file and resource flags", + args: []string{"backup", "--file", f.Name(), "--resource"}, + wantErrText: "if any flags in the group [file resource] are set none of the others can be; [file resource] were all set", + fmeflowBuild: 23166, + }, + { + name: "don't allow file and resource-name flags", + args: []string{"backup", "--file", f.Name(), "--resource-name", "test.fsconfig"}, + wantErrText: "if any flags in the group [file resource-name] are set none of the others can be; [file resource-name] were all set", + fmeflowBuild: 23166, + }, + { + name: "don't allow file and export-package flags", + args: []string{"backup", "--file", f.Name(), "--export-package", "FME_SHAREDRESOURCE_BACKUP"}, + wantErrText: "if any flags in the group [file export-package] are set none of the others can be; [export-package file] were all set", + fmeflowBuild: 23166, + }, + { + name: "don't allow file and failure-topic flags", + args: []string{"backup", "--file", f.Name(), "--failure-topic", "FAILURE_TOPIC"}, + wantErrText: "if any flags in the group [file failure-topic] are set none of the others can be; [failure-topic file] were all set", + fmeflowBuild: 23166, + }, + { + name: "don't allow file and success-topic flags", + args: []string{"backup", "--file", f.Name(), "--success-topic", "SUCCESS_TOPIC"}, + wantErrText: "if any flags in the group [file success-topic] are set none of the others can be; [file success-topic] were all set", + fmeflowBuild: 23166, + }, + { + name: "missing value for resource name", + args: []string{"backup", "--file", f.Name(), "--resource-name"}, + wantErrOutputRegex: "flag needs an argument: --resource-name", + fmeflowBuild: 23166, + }, + { + name: "missing value for export-package", + args: []string{"backup", "--file", f.Name(), "--export-package"}, + wantErrOutputRegex: "flag needs an argument: --export-package", + fmeflowBuild: 23166, + }, + { + name: "missing value for success topic", + args: []string{"backup", "--file", f.Name(), "--success-topic"}, + wantErrOutputRegex: "flag needs an argument: --success-topic", + fmeflowBuild: 23166, + }, + { + name: "missing value for failure-topic", + args: []string{"backup", "--file", f.Name(), "--failure-topic"}, + wantErrOutputRegex: "flag needs an argument: --failure-topic", + fmeflowBuild: 23166, + }, + } + + runTests(cases, t) + +} diff --git a/cmd/backup_v4_test.go b/cmd/backup_v4_test.go new file mode 100644 index 0000000..56fc224 --- /dev/null +++ b/cmd/backup_v4_test.go @@ -0,0 +1,145 @@ +package cmd + +import ( + "net/http" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBackupV4(t *testing.T) { + // standard responses for v3 and v4 + okResponseV4 := `Random file contents` + + // generate random file to back up to + f, err := os.CreateTemp("", "*fmeflow-backup.fsconfig") + require.NoError(t, err) + defer os.Remove(f.Name()) // clean up + + cases := []testCase{ + { + name: "unknown flag", + statusCode: http.StatusOK, + args: []string{"backup", "--badflag"}, + wantErrOutputRegex: "unknown flag: --badflag", + fmeflowBuild: 26000, + }, + { + name: "500 bad status code", + statusCode: http.StatusInternalServerError, + wantErrText: "500 Internal Server Error", + args: []string{"backup"}, + fmeflowBuild: 26000, + }, + { + name: "422 bad status code", + statusCode: http.StatusNotFound, + wantErrText: "404 Not Found", + args: []string{"backup"}, + fmeflowBuild: 26000, + }, + { + name: "backup to file", + statusCode: http.StatusOK, + args: []string{"backup", "--file", f.Name()}, + body: okResponseV4, + wantOutputRegex: "FME Server backed up to", + wantFileContents: fileContents{file: f.Name(), contents: okResponseV4}, + fmeflowBuild: 26000, + }, + { + name: "backup to shared resource", + statusCode: http.StatusAccepted, + args: []string{"backup", "--resource"}, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + wantBodyRegEx: `"resourceName":"FME_SHAREDRESOURCE_BACKUP"`, + fmeflowBuild: 26000, + }, + { + name: "export to specific file name", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--export-package", "TestPackageName.fsconfig"}, + wantBodyRegEx: `"resourceName":"FME_SHAREDRESOURCE_BACKUP".*"packagePath":"TestPackageName.fsconfig"`, + fmeflowBuild: 26000, + }, + { + name: "specify failure topic", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--failure-topic", "SAMPLE_TOPIC"}, + wantBodyRegEx: `"resourceName":"FME_SHAREDRESOURCE_BACKUP".*"failureTopic":"SAMPLE_TOPIC"`, + fmeflowBuild: 26000, + }, + { + name: "specify success topic", + statusCode: http.StatusAccepted, + body: `{"id":4}`, + wantOutputRegex: "Backup task submitted with id: 4", + args: []string{"backup", "--resource", "--success-topic", "SAMPLE_TOPIC"}, + wantBodyRegEx: `"resourceName":"FME_SHAREDRESOURCE_BACKUP".*"successTopic":"SAMPLE_TOPIC"`, + fmeflowBuild: 26000, + }, + { + name: "don't allow file and resource flags", + args: []string{"backup", "--file", f.Name(), "--resource"}, + wantErrText: "if any flags in the group [file resource] are set none of the others can be; [file resource] were all set", + fmeflowBuild: 26000, + }, + { + name: "don't allow file and resource-name flags", + args: []string{"backup", "--file", f.Name(), "--resource-name", "test.fsconfig"}, + wantErrText: "if any flags in the group [file resource-name] are set none of the others can be; [file resource-name] were all set", + fmeflowBuild: 26000, + }, + { + name: "don't allow file and export-package flags", + args: []string{"backup", "--file", f.Name(), "--export-package", "FME_SHAREDRESOURCE_BACKUP"}, + wantErrText: "if any flags in the group [file export-package] are set none of the others can be; [export-package file] were all set", + fmeflowBuild: 26000, + }, + { + name: "don't allow file and failure-topic flags", + args: []string{"backup", "--file", f.Name(), "--failure-topic", "FAILURE_TOPIC"}, + wantErrText: "if any flags in the group [file failure-topic] are set none of the others can be; [failure-topic file] were all set", + fmeflowBuild: 26000, + }, + { + name: "don't allow file and success-topic flags", + args: []string{"backup", "--file", f.Name(), "--success-topic", "SUCCESS_TOPIC"}, + wantErrText: "if any flags in the group [file success-topic] are set none of the others can be; [file success-topic] were all set", + fmeflowBuild: 26000, + }, + { + name: "missing value for resource name", + args: []string{"backup", "--file", f.Name(), "--resource-name"}, + wantErrOutputRegex: "flag needs an argument: --resource-name", + fmeflowBuild: 26000, + }, + { + name: "missing value for export-package", + args: []string{"backup", "--file", f.Name(), "--export-package"}, + wantErrOutputRegex: "flag needs an argument: --export-package", + fmeflowBuild: 26000, + }, + { + name: "missing value for success topic", + args: []string{"backup", "--file", f.Name(), "--success-topic"}, + wantErrOutputRegex: "flag needs an argument: --success-topic", + fmeflowBuild: 26000, + }, + { + name: "missing value for failure-topic", + args: []string{"backup", "--file", f.Name(), "--failure-topic"}, + wantErrOutputRegex: "flag needs an argument: --failure-topic", + fmeflowBuild: 26000, + }, + } + + runTests(cases, t) + +} diff --git a/docs/fmeflow_backup.md b/docs/fmeflow_backup.md index 0f2a1bf..90aab3d 100644 --- a/docs/fmeflow_backup.md +++ b/docs/fmeflow_backup.md @@ -24,13 +24,14 @@ fmeflow backup [flags] ### Options ``` + --api-version string The api version to use when contacting FME Server. Must be one of v3 or v4 --export-package string Path and name of the export package. (default "ServerConfigPackage.fsconfig") - --failure-topic string Topic to notify on failure of the backup. Default is MIGRATION_ASYNC_JOB_FAILURE + --failure-topic string Topic to notify on failure of the backup. In V3, default is MIGRATION_ASYNC_JOB_FAILURE -f, --file string Path to file to download the backup to. (default "ServerConfigPackage.fsconfig") -h, --help help for backup --resource Backup to a shared resource instead of downloading. --resource-name string Shared Resource Name where the exported package is saved. (default "FME_SHAREDRESOURCE_BACKUP") - --success-topic string Topic to notify on success of the backup. Default is MIGRATION_ASYNC_JOB_SUCCESS + --success-topic string Topic to notify on success of the backup. In V3, default is MIGRATION_ASYNC_JOB_SUCCESS ``` ### Options inherited from parent commands From b360bb51b8f6d0dc1ebd968a84166579decd46da Mon Sep 17 00:00:00 2001 From: Amber Xu Date: Tue, 2 Dec 2025 11:46:33 -0800 Subject: [PATCH 2/2] rename v3 backup test --- cmd/backup_test.go | 128 --------------------------------------------- 1 file changed, 128 deletions(-) delete mode 100644 cmd/backup_test.go diff --git a/cmd/backup_test.go b/cmd/backup_test.go deleted file mode 100644 index 0d168cd..0000000 --- a/cmd/backup_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package cmd - -import ( - "net/http" - "os" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestBackup(t *testing.T) { - // standard responses for v3 and v4 - okResponseV3 := `Random file contents` - - // generate random file to back up to - f, err := os.CreateTemp("", "*fmeflow-backup.fsconfig") - require.NoError(t, err) - defer os.Remove(f.Name()) // clean up - - cases := []testCase{ - { - name: "unknown flag", - statusCode: http.StatusOK, - args: []string{"backup", "--badflag"}, - wantErrOutputRegex: "unknown flag: --badflag", - }, - { - name: "500 bad status code", - statusCode: http.StatusInternalServerError, - wantErrText: "500 Internal Server Error", - args: []string{"backup"}, - }, - { - name: "422 bad status code", - statusCode: http.StatusNotFound, - wantErrText: "404 Not Found", - args: []string{"backup"}, - }, - { - name: "backup to file", - statusCode: http.StatusOK, - args: []string{"backup", "--file", f.Name()}, - body: okResponseV3, - wantOutputRegex: "FME Server backed up to", - wantFileContents: fileContents{file: f.Name(), contents: okResponseV3}, - }, - { - name: "backup to shared resource", - statusCode: http.StatusAccepted, - args: []string{"backup", "--resource"}, - body: `{"id":4}`, - wantOutputRegex: "Backup task submitted with id: 4", - wantFormParams: map[string]string{"resourceName": "FME_SHAREDRESOURCE_BACKUP"}, - }, - { - name: "export to specific file name", - statusCode: http.StatusAccepted, - body: `{"id":4}`, - wantOutputRegex: "Backup task submitted with id: 4", - args: []string{"backup", "--resource", "--export-package", "TestPackageName.fsconfig"}, - wantFormParams: map[string]string{"exportPackage": "TestPackageName.fsconfig", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, - }, - { - name: "specify failure topic", - statusCode: http.StatusAccepted, - body: `{"id":4}`, - wantOutputRegex: "Backup task submitted with id: 4", - args: []string{"backup", "--resource", "--failure-topic", "SAMPLE_TOPIC"}, - wantFormParams: map[string]string{"failureTopic": "SAMPLE_TOPIC", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, - }, - { - name: "specify success topic", - statusCode: http.StatusAccepted, - body: `{"id":4}`, - wantOutputRegex: "Backup task submitted with id: 4", - args: []string{"backup", "--resource", "--success-topic", "SAMPLE_TOPIC"}, - wantFormParams: map[string]string{"successTopic": "SAMPLE_TOPIC", "resourceName": "FME_SHAREDRESOURCE_BACKUP"}, - }, - { - name: "don't allow file and resource flags", - args: []string{"backup", "--file", f.Name(), "--resource"}, - wantErrText: "if any flags in the group [file resource] are set none of the others can be; [file resource] were all set", - }, - { - name: "don't allow file and resource-name flags", - args: []string{"backup", "--file", f.Name(), "--resource-name", "test.fsconfig"}, - wantErrText: "if any flags in the group [file resource-name] are set none of the others can be; [file resource-name] were all set", - }, - { - name: "don't allow file and export-package flags", - args: []string{"backup", "--file", f.Name(), "--export-package", "FME_SHAREDRESOURCE_BACKUP"}, - wantErrText: "if any flags in the group [file export-package] are set none of the others can be; [export-package file] were all set", - }, - { - name: "don't allow file and failure-topic flags", - args: []string{"backup", "--file", f.Name(), "--failure-topic", "FAILURE_TOPIC"}, - wantErrText: "if any flags in the group [file failure-topic] are set none of the others can be; [failure-topic file] were all set", - }, - { - name: "don't allow file and success-topic flags", - args: []string{"backup", "--file", f.Name(), "--success-topic", "SUCCESS_TOPIC"}, - wantErrText: "if any flags in the group [file success-topic] are set none of the others can be; [file success-topic] were all set", - }, - { - name: "missing value for resource name", - args: []string{"backup", "--file", f.Name(), "--resource-name"}, - wantErrOutputRegex: "flag needs an argument: --resource-name", - }, - { - name: "missing value for export-package", - args: []string{"backup", "--file", f.Name(), "--export-package"}, - wantErrOutputRegex: "flag needs an argument: --export-package", - }, - { - name: "missing value for success topic", - args: []string{"backup", "--file", f.Name(), "--success-topic"}, - wantErrOutputRegex: "flag needs an argument: --success-topic", - }, - { - name: "missing value for failure-topic", - args: []string{"backup", "--file", f.Name(), "--failure-topic"}, - wantErrOutputRegex: "flag needs an argument: --failure-topic", - }, - } - - runTests(cases, t) - -}