Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/stackit_load-balancer_target-pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ stackit load-balancer target-pool [flags]

* [stackit load-balancer](./stackit_load-balancer.md) - Provides functionality for Load Balancer
* [stackit load-balancer target-pool add-target](./stackit_load-balancer_target-pool_add-target.md) - Adds a target to a target pool
* [stackit load-balancer target-pool describe](./stackit_load-balancer_target-pool_describe.md) - Shows details of a target pool in a Load Balancer
* [stackit load-balancer target-pool remove-target](./stackit_load-balancer_target-pool_remove-target.md) - Removes a target from a target pool

43 changes: 43 additions & 0 deletions docs/stackit_load-balancer_target-pool_describe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## stackit load-balancer target-pool describe

Shows details of a target pool in a Load Balancer

### Synopsis

Shows details of a target pool in a Load Balancer.

```
stackit load-balancer target-pool describe TARGET_POOL_NAME [flags]
```

### Examples

```
Get details of a target pool with name "pool" in load balancer with name "my-load-balancer"
$ stackit load-balancer target-pool describe pool --lb-name my-load-balancer

Get details of a target pool with name "pool" in load balancer with name "my-load-balancer in JSON output"
$ stackit load-balancer target-pool describe pool --lb-name my-load-balancer --output-format json
```

### Options

```
-h, --help Help for "stackit load-balancer target-pool describe"
--lb-name string Name of the load balancer
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none"]
-p, --project-id string Project ID
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```

### SEE ALSO

* [stackit load-balancer target-pool](./stackit_load-balancer_target-pool.md) - Provides functionality for target pools

203 changes: 203 additions & 0 deletions internal/cmd/load-balancer/target-pool/describe/describe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package describe

import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"

"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/client"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/load-balancer/utils"
"github.com/stackitcloud/stackit-cli/internal/pkg/tables"

"github.com/spf13/cobra"
"github.com/stackitcloud/stackit-sdk-go/services/loadbalancer"
)

const (
targetPoolNameArg = "TARGET_POOL_NAME"

lbNameFlag = "lb-name"
)

type inputModel struct {
*globalflags.GlobalFlagModel
TargetPoolName string
LBName string
}

func NewCmd(p *print.Printer) *cobra.Command {
cmd := &cobra.Command{
Use: fmt.Sprintf("describe %s", targetPoolNameArg),
Short: "Shows details of a target pool in a Load Balancer",
Long: "Shows details of a target pool in a Load Balancer.",
Args: args.SingleArg(targetPoolNameArg, nil),
Example: examples.Build(
examples.NewExample(
`Get details of a target pool with name "pool" in load balancer with name "my-load-balancer"`,
"$ stackit load-balancer target-pool describe pool --lb-name my-load-balancer"),
examples.NewExample(
`Get details of a target pool with name "pool" in load balancer with name "my-load-balancer in JSON output"`,
"$ stackit load-balancer target-pool describe pool --lb-name my-load-balancer --output-format json"),
),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
model, err := parseInput(p, cmd, args)
if err != nil {
return err
}
// Configure API client
apiClient, err := client.ConfigureClient(p)
if err != nil {
return err
}

// Call API
req := buildRequest(ctx, model, apiClient)
resp, err := req.Execute()
if err != nil {
return fmt.Errorf("read load balancer: %w", err)
}

Comment thread
DiogoFerrao marked this conversation as resolved.
targetPool := utils.FindLoadBalancerTargetPoolByName(*resp.TargetPools, model.TargetPoolName)
if targetPool == nil {
return fmt.Errorf("target pool not found")
}

listener := utils.FindLoadBalancerListenerByTargetPool(*resp.Listeners, *targetPool.Name)

return outputResult(p, model.OutputFormat, *targetPool, listener)
},
}
configureFlags(cmd)
return cmd
}

func configureFlags(cmd *cobra.Command) {
cmd.Flags().String(lbNameFlag, "", "Name of the load balancer")

err := flags.MarkFlagsRequired(cmd, lbNameFlag)
cobra.CheckErr(err)
}

func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
targetPoolName := inputArgs[0]

globalFlags := globalflags.Parse(p, cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}

model := inputModel{
GlobalFlagModel: globalFlags,
TargetPoolName: targetPoolName,
LBName: cmd.Flag(lbNameFlag).Value.String(),
}

if p.IsVerbosityDebug() {
modelStr, err := print.BuildDebugStrFromInputModel(model)
if err != nil {
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
} else {
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
}
}

return &model, nil
}

func buildRequest(ctx context.Context, model *inputModel, apiClient *loadbalancer.APIClient) loadbalancer.ApiGetLoadBalancerRequest {
req := apiClient.GetLoadBalancer(ctx, model.ProjectId, model.LBName)
return req
}

func outputResult(p *print.Printer, outputFormat string, targetPool loadbalancer.TargetPool, listener *loadbalancer.Listener) error {
switch outputFormat {
case print.JSONOutputFormat:
output := struct {
*loadbalancer.TargetPool
Listener *loadbalancer.Listener `json:"attached_listener"`
}{
&targetPool,
listener,
}
details, err := json.MarshalIndent(output, "", " ")
if err != nil {
return fmt.Errorf("marshal load balancer: %w", err)
}
p.Outputln(string(details))

return nil
default:
return outputResultAsTable(p, targetPool, listener)
}
}

func outputResultAsTable(p *print.Printer, targetPool loadbalancer.TargetPool, listener *loadbalancer.Listener) error {
sessionPersistence := "None"
if targetPool.SessionPersistence != nil && targetPool.SessionPersistence.UseSourceIpAddress != nil && *targetPool.SessionPersistence.UseSourceIpAddress {
sessionPersistence = "Use Source IP"
}
Comment thread
DiogoFerrao marked this conversation as resolved.

healthCheckInterval := "-"
healthCheckUnhealthyThreshold := "-"
healthCheckHealthyThreshold := "-"
if targetPool.ActiveHealthCheck != nil {
if targetPool.ActiveHealthCheck.Interval != nil {
healthCheckInterval = *targetPool.ActiveHealthCheck.Interval
}
if targetPool.ActiveHealthCheck.UnhealthyThreshold != nil {
healthCheckUnhealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.UnhealthyThreshold, 10)
}
if targetPool.ActiveHealthCheck.HealthyThreshold != nil {
healthCheckHealthyThreshold = strconv.FormatInt(*targetPool.ActiveHealthCheck.HealthyThreshold, 10)
}
}

targets := "-"
if targetPool.Targets != nil {
var targetsSlice []string
for _, target := range *targetPool.Targets {
targetStr := fmt.Sprintf("%s (%s)", *target.DisplayName, *target.Ip)
targetsSlice = append(targetsSlice, targetStr)
}
targets = strings.Join(targetsSlice, "\n")
}

listenerStr := "-"
if listener != nil {
listenerStr = fmt.Sprintf("%s (Port:%d, Protocol: %s)", *listener.Name, *listener.Port, *listener.Protocol)
}

table := tables.NewTable()
Comment thread
DiogoFerrao marked this conversation as resolved.
table.AddRow("NAME", *targetPool.Name)
table.AddSeparator()
table.AddRow("TARGET PORT", *targetPool.TargetPort)
table.AddSeparator()
table.AddRow("ATTACHED LISTENER", listenerStr)
table.AddSeparator()
table.AddRow("TARGETS", targets)
table.AddSeparator()
table.AddRow("SESSION PERSISTENCE", sessionPersistence)
table.AddSeparator()
table.AddRow("HEALTH CHECK INTERVAL", healthCheckInterval)
table.AddSeparator()
table.AddRow("HEALTH CHECK DOWN AFTER", healthCheckUnhealthyThreshold)
table.AddSeparator()
table.AddRow("HEALTH CHECK UP AFTER", healthCheckHealthyThreshold)
table.AddSeparator()

err := p.PagerDisplay(table.Render())
if err != nil {
return fmt.Errorf("display output: %w", err)
}

return nil
}
Loading