Files
influx-cli/clients/stacks/stacks.go
Simon Richardson e2aa4d2df9 fix(stacks): Fix stack error typo (#445)
This is a simple fix for typo in an error returned to the user.
2022-09-22 15:39:48 +01:00

215 lines
5.2 KiB
Go

package stacks
import (
"context"
"fmt"
"sort"
"github.com/influxdata/influx-cli/v2/api"
"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influx-cli/v2/pkg/template"
)
type Client struct {
clients.CLI
api.StacksApi
api.OrganizationsApi
api.TemplatesApi
}
type ListParams struct {
clients.OrgParams
StackIds []string
StackNames []string
}
func (c Client) List(ctx context.Context, params *ListParams) error {
orgId, err := params.GetOrgID(ctx, c.ActiveConfig, c.OrganizationsApi)
if err != nil {
return err
}
res, err := c.ListStacks(ctx).OrgID(orgId).Name(params.StackNames).StackID(params.StackIds).Execute()
if err != nil {
return fmt.Errorf("failed to list stacks: %w", err)
}
return c.printStacks(stackPrintOptions{stacks: res.Stacks})
}
type InitParams struct {
clients.OrgParams
Name string
Description string
URLs []string
}
func (c Client) Init(ctx context.Context, params *InitParams) error {
orgId, err := params.GetOrgID(ctx, c.ActiveConfig, c.OrganizationsApi)
if err != nil {
return err
}
req := api.StackPostRequest{
OrgID: orgId,
Name: params.Name,
Urls: params.URLs,
}
if params.Description != "" {
req.Description = &params.Description
}
stack, err := c.CreateStack(ctx).StackPostRequest(req).Execute()
if err != nil {
return fmt.Errorf("failed to create stack %q: %w", params.Name, err)
}
return c.printStacks(stackPrintOptions{stack: &stack})
}
type RemoveParams struct {
clients.OrgParams
Ids []string
Force bool
}
func (c Client) Remove(ctx context.Context, params *RemoveParams) error {
orgId, err := params.GetOrgID(ctx, c.ActiveConfig, c.OrganizationsApi)
if err != nil {
return err
}
stacks, err := c.ListStacks(ctx).OrgID(orgId).StackID(params.Ids).Execute()
if err != nil {
return fmt.Errorf("failed to look up stacks: %w", err)
}
for _, stack := range stacks.Stacks {
if err := c.printStacks(stackPrintOptions{stack: &stack}); err != nil {
return err
}
if !params.Force && !c.StdIO.GetConfirm(fmt.Sprintf("Confirm removal of the stack[%s] and all associated resources", stack.Id)) {
continue
}
if err := c.DeleteStack(ctx, stack.Id).OrgID(orgId).Execute(); err != nil {
return fmt.Errorf("failed to delete stack %q: %w", stack.Id, err)
}
}
return nil
}
type AddedResource struct {
Kind string
Id string
}
type UpdateParams struct {
Id string
Name *string
Description *string
URLs []string
AddedResources []AddedResource
template.OutParams
}
func (c Client) Update(ctx context.Context, params *UpdateParams) error {
req := api.StackPatchRequest{
Name: params.Name,
Description: params.Description,
TemplateURLs: params.URLs,
AdditionalResources: make([]api.StackPatchRequestResource, len(params.AddedResources)),
}
for i, r := range params.AddedResources {
req.AdditionalResources[i] = api.StackPatchRequestResource{
ResourceID: r.Id,
Kind: r.Kind,
}
}
stack, err := c.UpdateStack(ctx, params.Id).StackPatchRequest(req).Execute()
if err != nil {
return fmt.Errorf("failed to update stack %q: %w", params.Id, err)
}
if err := c.printStacks(stackPrintOptions{stack: &stack}); err != nil {
return err
}
// Can skip exporting the updated template if no resources were added.
if len(params.AddedResources) == 0 {
return nil
}
if !c.StdIO.GetConfirm(`Your stack now differs from your template. Applying an outdated template will revert these updates.
Export a new template with these updates to prevent accidental changes?`) {
return nil
}
exportReq := api.TemplateExport{StackID: &stack.Id}
tmpl, err := c.ExportTemplate(ctx).TemplateExport(exportReq).Execute()
if err != nil {
return fmt.Errorf("failed to export stack %q: %w", stack.Id, err)
}
if err := params.OutParams.WriteTemplate(tmpl); err != nil {
return fmt.Errorf("failed to write exported template: %w", err)
}
return nil
}
type stackPrintOptions struct {
stack *api.Stack
stacks []api.Stack
}
func (c Client) printStacks(options stackPrintOptions) error {
if c.PrintAsJSON {
var v interface{}
if options.stack != nil {
v = options.stack
} else {
v = options.stacks
}
return c.PrintJSON(v)
}
headers := []string{"ID", "OrgID", "Active", "Name", "Description", "Num Resources", "Sources", "URLs", "Created At", "Updated At"}
stacks := options.stacks
if options.stack != nil {
stacks = append(stacks, *options.stack)
}
var rows []map[string]interface{}
for _, s := range stacks {
var latestEvent api.StackEvent
if len(s.Events) > 0 {
sort.Slice(s.Events, func(i, j int) bool {
return s.Events[i].UpdatedAt.Before(s.Events[j].UpdatedAt)
})
latestEvent = s.Events[len(s.Events)-1]
}
var desc string
if latestEvent.Description != nil {
desc = *latestEvent.Description
}
row := map[string]interface{}{
"ID": s.Id,
"OrgID": s.OrgID,
"Active": latestEvent.EventType != "uninstall",
"Name": latestEvent.Name,
"Description": desc,
"Num Resources": len(latestEvent.Resources),
"Sources": latestEvent.Sources,
"URLs": latestEvent.Urls,
"Created At": s.CreatedAt,
"Updated At": latestEvent.UpdatedAt,
}
rows = append(rows, row)
}
return c.PrintTable(headers, rows...)
}