diff --git a/clients/export/export.go b/clients/export/export.go index 0ea22dd..56ab65a 100644 --- a/clients/export/export.go +++ b/clients/export/export.go @@ -110,3 +110,26 @@ func (c Client) ExportAll(ctx context.Context, params *AllParams) error { } return nil } + +type StackParams struct { + OutParams + StackId string +} + +func (c Client) ExportStack(ctx context.Context, params *StackParams) error { + if params.StackId == "" { + return fmt.Errorf("no stack id provided") + } + + exportReq := api.TemplateExport{StackID: ¶ms.StackId} + tmpl, err := c.ExportTemplate(ctx).TemplateExport(exportReq).Execute() + + if err != nil { + return fmt.Errorf("failed to export stack %q: %w", params.StackId, err) + } + if err := params.OutParams.writeTemplate(tmpl); err != nil { + return fmt.Errorf("failed to write exported template: %w", err) + } + + return nil +} diff --git a/cmd/influx/export.go b/cmd/influx/export.go index f9bbf60..820f20d 100644 --- a/cmd/influx/export.go +++ b/cmd/influx/export.go @@ -66,6 +66,7 @@ For information about exporting InfluxDB templates, see https://docs.influxdata.com/influxdb/latest/reference/cli/influx/export/`, Subcommands: []*cli.Command{ newExportAllCmd(), + newExportStackCmd(), }, Flags: append( commonFlagsNoPrint(), @@ -360,6 +361,65 @@ https://docs.influxdata.com/influxdb/latest/reference/cli/influx/export/all/ } } +func newExportStackCmd() *cli.Command { + var params struct { + out string + } + + return &cli.Command{ + Name: "stack", + Usage: "Export all resources associated with a stack as a template", + Description: `The influx export stack command exports all resources +associated with a stack as a template. All metadata.name fields remain the same. + +Example: + # Export a stack as a template + influx export stack $STACK_ID + +For information about exporting InfluxDB templates, see +https://docs.influxdata.com/influxdb/latest/reference/cli/influx/export/ +and +https://docs.influxdata.com/influxdb/latest/reference/cli/influx/export/stack/ +`, + Flags: append( + commonFlagsNoPrint(), + &cli.StringFlag{ + Name: "file", + Usage: "Output file for created template; defaults to std out if no file provided; the extension of provided file (.yml/.json) will dictate encoding", + Aliases: []string{"f"}, + Destination: ¶ms.out, + }, + ), + Before: middleware.WithBeforeFns(withCli(), withApi(true)), + Action: func(ctx *cli.Context) error { + if ctx.NArg() != 1 { + return fmt.Errorf("incorrect number of arguments, expected one for ") + } + + parsedParams := export.StackParams{ + StackId: ctx.Args().Get(0), + } + + outParams, closer, err := parseOutParams(params.out) + if closer != nil { + defer closer() + } + if err != nil { + return err + } + parsedParams.OutParams = outParams + + apiClient := getAPI(ctx) + client := export.Client{ + CLI: getCLI(ctx), + TemplatesApi: apiClient.TemplatesApi, + OrganizationsApi: apiClient.OrganizationsApi, + } + return client.ExportStack(ctx.Context, &parsedParams) + }, + } +} + func splitNonEmpty(s string) []string { if s == "" { return nil