From 364c1310c23d7b90994f204c4a315c242d94277f Mon Sep 17 00:00:00 2001 From: shi yuhang <52435083+shiyuhang0@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:14:01 +0800 Subject: [PATCH] Export command fix (#237) ## What is the purpose of the change ## Brief change log --- .../generate_doc/ticloud_serverless_create.md | 4 ++-- .../ticloud_serverless_export_create.md | 5 ++-- .../ticloud_serverless_import_start.md | 23 +++++++++++++------ internal/cli/serverless/create.go | 4 ++-- internal/cli/serverless/export/create.go | 19 +++++++++++++++ internal/cli/serverless/export/ui.go | 1 + internal/cli/serverless/update.go | 13 +++++++---- .../v1beta1/serverless/export.swagger.json | 13 +---------- .../serverless/export/api/openapi.yaml | 11 +-------- .../serverless/export/api_export_service.go | 13 +---------- ...port_service_download_export_files_body.go | 2 +- 11 files changed, 56 insertions(+), 52 deletions(-) diff --git a/docs/generate_doc/ticloud_serverless_create.md b/docs/generate_doc/ticloud_serverless_create.md index 9508a160..6955587a 100644 --- a/docs/generate_doc/ticloud_serverless_create.md +++ b/docs/generate_doc/ticloud_serverless_create.md @@ -22,9 +22,9 @@ ticloud serverless create [flags] ### Options ``` - --disable-public-endpoint Whether the public endpoint is disabled. (optional) + --disable-public-endpoint Whether the public endpoint is disabled. -n, --display-name string Display name of the cluster to de created. - --encryption Whether Enhanced Encryption at Rest is enabled. (optional) + --encryption Whether Enhanced Encryption at Rest is enabled. -h, --help help for create -p, --project-id string The ID of the project, in which the cluster will be created. (default: "default project") -r, --region string The name of cloud region. You can use "ticloud serverless region" to see all regions. diff --git a/docs/generate_doc/ticloud_serverless_export_create.md b/docs/generate_doc/ticloud_serverless_export_create.md index 2fe01609..8a7a6447 100644 --- a/docs/generate_doc/ticloud_serverless_export_create.md +++ b/docs/generate_doc/ticloud_serverless_export_create.md @@ -18,7 +18,7 @@ ticloud serverless export create [flags] Export all data with S3 type in non-interactive mode: $ ticloud serverless export create -c --target-type S3 --s3.uri --s3.access-key-id --s3.secret-access-key - Export all data and customize csv format in non-interactive mode: + Export all data and customize CSV format in non-interactive mode: $ ticloud serverless export create -c --file-type CSV --csv.separator ";" --csv.delimiter "\"" --csv.null-value 'NaN' --csv.skip-header Export test.t1 and test.t2 in non-interactive mode: @@ -39,7 +39,8 @@ ticloud serverless export create [flags] --csv.null-value string Representation of null values in CSV files. (default "\\N") --csv.separator string Separator of each value in CSV files. (default ",") --csv.skip-header Export CSV files of the tables without header. - --file-type string The export file type. One of ["CSV" "SQL" "PARQUET"]. (default "CSV") + --display-name string The display name of the export. (default: SNAPSHOT_) + --file-type string The export file type. One of ["SQL" "CSV" "PARQUET"]. (default "CSV") --filter strings Specify the exported table(s) with table filter patterns. See https://docs.pingcap.com/tidb/stable/table-filter to learn table filter. --force Create without confirmation. You need to confirm when you want to export the whole cluster in non-interactive mode. --gcs.service-account-key string The base64 encoded service account key of GCS. diff --git a/docs/generate_doc/ticloud_serverless_import_start.md b/docs/generate_doc/ticloud_serverless_import_start.md index 8d061d83..47ff6247 100644 --- a/docs/generate_doc/ticloud_serverless_import_start.md +++ b/docs/generate_doc/ticloud_serverless_import_start.md @@ -21,6 +21,15 @@ ticloud serverless import start [flags] Start a local import task with custom CSV format: $ ticloud serverless import start --local.file-path --cluster-id --file-type CSV --local.target-database --local.target-table --csv.separator \" --csv.delimiter \' --csv.backslash-escape=false --csv.trim-last-separator=true + Start an S3 import task in non-interactive mode: + $ ticloud serverless import start --source-type S3 --s3.uri --cluster-id --file-type --s3.role-arn + + Start a GCS import task in non-interactive mode: + $ ticloud serverless import start --source-type GCS --gcs.uri --cluster-id --file-type --gcs.service-account-key + + Start an Azure Blob import task in non-interactive mode: + $ ticloud serverless import start --source-type AZURE_BLOB --azblob.uri --cluster-id --file-type --azblob.sas-token + ``` ### Options @@ -36,19 +45,19 @@ ticloud serverless import start [flags] --csv.separator string The field separator of CSV file. (default ",") --csv.skip-header Specifies whether the CSV file contains a header line. --csv.trim-last-separator Specifies whether to treat separator as the line terminator and trim all trailing separators in the CSV file. - --file-type string The import file type, one of ["CSV"]. + --file-type string The import file type, one of ["CSV" "SQL" "AURORA_SNAPSHOT" "PARQUET"]. --gcs.service-account-key string The base64 encoded service account key of GCS. - --gcs.uri string The GCS folder URI for import. + --gcs.uri string The GCS URI in gcs:/// format. Required when source type is GCS. -h, --help help for start --local.concurrency int The concurrency for uploading file. (default 5) --local.file-path string The local file path to import. --local.target-database string Target database to which import data. --local.target-table string Target table to which import data. - --s3.access-key-id string The access key ID for S3. - --s3.role-arn string The role ARN for S3. - --s3.secret-access-key string The secret access key for S3. - --s3.uri string The S3 folder URI for import. - --source-type string The import source type, one of ["S3" "LOCAL" "GCS" "AZURE_BLOB"]. (default "LOCAL") + --s3.access-key-id string The access key ID of the S3. You only need to set one of the s3.role-arn and [s3.access-key-id, s3.secret-access-key]. + --s3.role-arn string The role arn of the S3. You only need to set one of the s3.role-arn and [s3.access-key-id, s3.secret-access-key]. + --s3.secret-access-key string The secret access key of the S3. You only need to set one of the s3.role-arn and [s3.access-key-id, s3.secret-access-key]. + --s3.uri string The S3 URI in s3:/// format. Required when source type is S3. + --source-type string The import source type, one of ["LOCAL" "S3" "GCS" "AZURE_BLOB"]. (default "LOCAL") ``` ### Options inherited from parent commands diff --git a/internal/cli/serverless/create.go b/internal/cli/serverless/create.go index 7cb35575..d63f11f3 100644 --- a/internal/cli/serverless/create.go +++ b/internal/cli/serverless/create.go @@ -306,8 +306,8 @@ func CreateCmd(h *internal.Helper) *cobra.Command { createCmd.Flags().StringP(flag.Region, flag.RegionShort, "", "The name of cloud region. You can use \"ticloud serverless region\" to see all regions.") createCmd.Flags().StringP(flag.ProjectID, flag.ProjectIDShort, "", "The ID of the project, in which the cluster will be created. (default: \"default project\")") createCmd.Flags().Int32(flag.SpendingLimitMonthly, 0, "Maximum monthly spending limit in USD cents. (optional)") - createCmd.Flags().Bool(flag.Encryption, false, "Whether Enhanced Encryption at Rest is enabled. (optional)") - createCmd.Flags().Bool(flag.PublicEndpointDisabled, false, "Whether the public endpoint is disabled. (optional)") + createCmd.Flags().Bool(flag.Encryption, false, "Whether Enhanced Encryption at Rest is enabled.") + createCmd.Flags().Bool(flag.PublicEndpointDisabled, false, "Whether the public endpoint is disabled.") return createCmd } diff --git a/internal/cli/serverless/export/create.go b/internal/cli/serverless/export/create.go index 30ada522..e3910dcf 100644 --- a/internal/cli/serverless/export/create.go +++ b/internal/cli/serverless/export/create.go @@ -69,6 +69,7 @@ func (c CreateOpts) NonInteractiveFlags() []string { flag.AzureBlobURI, flag.AzureBlobSASToken, flag.ParquetCompression, + flag.DisplayName, } } @@ -154,6 +155,7 @@ func CreateCmd(h *internal.Helper) *cobra.Command { var gcsURI, gcsServiceAccountKey string // azure var azBlobURI, azBlobSasToken string + var displayName string if opts.interactive { if !h.IOStreams.CanPrompt { @@ -171,6 +173,15 @@ func CreateCmd(h *internal.Helper) *cobra.Command { } clusterId = cluster.ID + // display name + fmt.Fprintln(h.IOStreams.Out, color.HiGreenString("Input the display name (optional):")) + inputs := []string{flag.DisplayName} + textInput, err := ui.InitialInputModel(inputs, inputDescription) + if err != nil { + return err + } + displayName = textInput.Inputs[0].Value() + // target targetType, err = GetSelectedTargetType() if err != nil { @@ -369,6 +380,10 @@ func CreateCmd(h *internal.Helper) *cobra.Command { } else { // non-interactive mode, get values from flags var err error + displayName, err = cmd.Flags().GetString(flag.DisplayName) + if err != nil { + return errors.Trace(err) + } clusterId, err = cmd.Flags().GetString(flag.ClusterID) if err != nil { return errors.Trace(err) @@ -544,6 +559,9 @@ func CreateCmd(h *internal.Helper) *cobra.Command { Type: &targetType, }, } + if displayName != "" { + params.DisplayName = &displayName + } // add target switch targetType { case export.EXPORTTARGETTYPEENUM_S3: @@ -642,6 +660,7 @@ func CreateCmd(h *internal.Helper) *cobra.Command { createCmd.Flags().String(flag.AzureBlobURI, "", "The Azure Blob URI in azure://.blob.core.windows.net// format. Required when target type is AZURE_BLOB.") createCmd.Flags().String(flag.AzureBlobSASToken, "", "The SAS token of Azure Blob.") createCmd.Flags().String(flag.ParquetCompression, "ZSTD", fmt.Sprintf("The parquet compression algorithm. One of %q.", export.AllowedExportParquetCompressionTypeEnumEnumValues)) + createCmd.Flags().String(flag.DisplayName, "", "The display name of the export. (default: SNAPSHOT_)") createCmd.MarkFlagsMutuallyExclusive(flag.TableFilter, flag.SQL) createCmd.MarkFlagsMutuallyExclusive(flag.TableWhere, flag.SQL) diff --git a/internal/cli/serverless/export/ui.go b/internal/cli/serverless/export/ui.go index f6501433..39595493 100644 --- a/internal/cli/serverless/export/ui.go +++ b/internal/cli/serverless/export/ui.go @@ -42,6 +42,7 @@ var inputDescription = map[string]string{ flag.CSVDelimiter: "Input the CSV delimiter: delimiter of string type variables in CSV files, skip to use default value (\"). If you want to set empty string, please use non-interactive mode", flag.CSVNullValue: "Input the CSV null value: representation of null values in CSV files, skip to use default value (\\N). If you want to set empty string, please use non-interactive mode", flag.CSVSkipHeader: "Input the CSV skip header: export CSV files of the tables without header. Type `true` to skip header, others will not skip header", + flag.DisplayName: "Input the name of export. You can skip and use the default name SNAPSHOT_ by pressing Enter", } func GetSelectedParquetCompression() (export.ExportParquetCompressionTypeEnum, error) { diff --git a/internal/cli/serverless/update.go b/internal/cli/serverless/update.go index 7ffaf528..c9a265fe 100644 --- a/internal/cli/serverless/update.go +++ b/internal/cli/serverless/update.go @@ -138,14 +138,14 @@ func UpdateCmd(h *internal.Helper) *cobra.Command { return err } - if fieldName == string(PublicEndpointDisabledHumanReadable) { + if fieldName == PublicEndpointDisabledHumanReadable { publicEndpointDisabled, err = cloud.GetSelectedBool("Disable the public endpoint of the cluster?") if err != nil { return err } } else { // variables for input - inputModel, err := GetUpdateClusterInput() + inputModel, err := GetUpdateClusterInput(fieldName) if err != nil { return err } @@ -223,14 +223,19 @@ func UpdateCmd(h *internal.Helper) *cobra.Command { return updateCmd } -func GetUpdateClusterInput() (tea.Model, error) { +func GetUpdateClusterInput(fieldName string) (tea.Model, error) { m := ui.TextInputModel{ Inputs: make([]textinput.Model, 1), } t := textinput.New() t.Cursor.Style = config.CursorStyle t.CharLimit = 64 - t.Placeholder = "New value" + switch fieldName { + case string(Labels): + t.Placeholder = "update labels, e.g. {\"label1\":\"value1\",\"label2\":\"value2\"}" + default: + t.Placeholder = "new value" + } t.Focus() t.PromptStyle = config.FocusedStyle t.TextStyle = config.FocusedStyle diff --git a/pkg/tidbcloud/v1beta1/serverless/export.swagger.json b/pkg/tidbcloud/v1beta1/serverless/export.swagger.json index 20fa2820..7737f1cf 100644 --- a/pkg/tidbcloud/v1beta1/serverless/export.swagger.json +++ b/pkg/tidbcloud/v1beta1/serverless/export.swagger.json @@ -221,14 +221,6 @@ "in": "path", "required": true, "type": "string" - }, - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/ExportService.CancelExportBody" - } } ], "tags": [ @@ -760,9 +752,6 @@ ], "description": " - ROLE_ARN: The access method is role arn.\n - ACCESS_KEY: The access method is access key." }, - "ExportService.CancelExportBody": { - "type": "object" - }, "ExportService.CreateExportBody": { "type": "object", "properties": { @@ -799,7 +788,7 @@ "items": { "type": "string" }, - "description": "Required. The name of the files to be downloaded." + "description": "Required. The name of the files to download." } }, "required": [ diff --git a/pkg/tidbcloud/v1beta1/serverless/export/api/openapi.yaml b/pkg/tidbcloud/v1beta1/serverless/export/api/openapi.yaml index d7d99618..a489e959 100644 --- a/pkg/tidbcloud/v1beta1/serverless/export/api/openapi.yaml +++ b/pkg/tidbcloud/v1beta1/serverless/export/api/openapi.yaml @@ -163,12 +163,6 @@ paths: required: true schema: type: string - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ExportService.CancelExportBody' - required: true responses: "200": content: @@ -185,7 +179,6 @@ paths: summary: Cancel a specific export job. tags: - ExportService - x-codegen-request-body-name: body /v1beta1/clusters/{clusterId}/exports/{exportId}:download: post: deprecated: true @@ -633,8 +626,6 @@ components: - ROLE_ARN - ACCESS_KEY type: string - ExportService.CancelExportBody: - type: object ExportService.CreateExportBody: properties: exportOptions: @@ -656,7 +647,7 @@ components: ExportService.DownloadExportFilesBody: properties: fileNames: - description: Required. The name of the files to be downloaded. + description: Required. The name of the files to download. items: type: string type: array diff --git a/pkg/tidbcloud/v1beta1/serverless/export/api_export_service.go b/pkg/tidbcloud/v1beta1/serverless/export/api_export_service.go index 1d22c6bb..e4052740 100644 --- a/pkg/tidbcloud/v1beta1/serverless/export/api_export_service.go +++ b/pkg/tidbcloud/v1beta1/serverless/export/api_export_service.go @@ -27,12 +27,6 @@ type ApiExportServiceCancelExportRequest struct { ApiService *ExportServiceAPIService clusterId string exportId string - body *map[string]interface{} -} - -func (r ApiExportServiceCancelExportRequest) Body(body map[string]interface{}) ApiExportServiceCancelExportRequest { - r.body = &body - return r } func (r ApiExportServiceCancelExportRequest) Execute() (*Export, *http.Response, error) { @@ -79,12 +73,9 @@ func (a *ExportServiceAPIService) ExportServiceCancelExportExecute(r ApiExportSe localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.body == nil { - return localVarReturnValue, nil, reportError("body is required and must be specified") - } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -100,8 +91,6 @@ func (a *ExportServiceAPIService) ExportServiceCancelExportExecute(r ApiExportSe if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.body req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err diff --git a/pkg/tidbcloud/v1beta1/serverless/export/model_export_service_download_export_files_body.go b/pkg/tidbcloud/v1beta1/serverless/export/model_export_service_download_export_files_body.go index 23a5637f..67a745ed 100644 --- a/pkg/tidbcloud/v1beta1/serverless/export/model_export_service_download_export_files_body.go +++ b/pkg/tidbcloud/v1beta1/serverless/export/model_export_service_download_export_files_body.go @@ -20,7 +20,7 @@ var _ MappedNullable = &ExportServiceDownloadExportFilesBody{} // ExportServiceDownloadExportFilesBody struct for ExportServiceDownloadExportFilesBody type ExportServiceDownloadExportFilesBody struct { - // Required. The name of the files to be downloaded. + // Required. The name of the files to download. FileNames []string `json:"fileNames"` AdditionalProperties map[string]interface{} }