Skip to content

Commit

Permalink
Introduce support for droplet autoscaler (#1606)
Browse files Browse the repository at this point in the history
* Setup client methods and regen mocks

* Support droplet autoscale cli methods

* Add unit tests

* Visualize new lb feature flags

* Hydrate missing tests

* PR feedback

* Use positional args

* Hide droplet-autoscale at cmd root
  • Loading branch information
asaha2 authored Nov 15, 2024
1 parent 5ad687a commit fbf093f
Show file tree
Hide file tree
Showing 46 changed files with 1,141 additions and 2 deletions.
18 changes: 18 additions & 0 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ const (
ArgMajorVersion = "major-version"
// ArgAutoUpgrade is a cluster's auto-upgrade argument.
ArgAutoUpgrade = "auto-upgrade"

// ArgAutoscaleID is an autoscale id argument.
ArgAutoscaleID = "id"
// ArgAutoscaleName is an autoscale name argument.
ArgAutoscaleName = "name"
// ArgAutoscaleMinInstances is an autoscale min instance argument.
ArgAutoscaleMinInstances = "min-instances"
// ArgAutoscaleMaxInstances is an autoscale max instance argument.
ArgAutoscaleMaxInstances = "max-instances"
// ArgAutoscaleCpuTarget is an autoscale target cpu utilization argument.
ArgAutoscaleCpuTarget = "cpu-target"
// ArgAutoscaleMemTarget is an autoscale target memory utilization argument.
ArgAutoscaleMemTarget = "mem-target"
// ArgAutoscaleCooldownMinutes is an autoscale cooldown duration (minutes) argument.
ArgAutoscaleCooldownMinutes = "cooldown-minutes"
// ArgAutoscaleTargetInstances is an autoscale target instance argument.
ArgAutoscaleTargetInstances = "target-instances"

// ArgHA is a cluster's highly available control plane argument.
ArgHA = "ha"
// ArgEnableControlPlaneFirewall enable control plane firewall.
Expand Down
2 changes: 2 additions & 0 deletions commands/command_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type CmdConfig struct {
ReservedIPActions func() do.ReservedIPActionsService
Droplets func() do.DropletsService
DropletActions func() do.DropletActionsService
DropletAutoscale func() do.DropletAutoscaleService
Domains func() do.DomainsService
Actions func() do.ActionsService
Account func() do.AccountService
Expand Down Expand Up @@ -99,6 +100,7 @@ func NewCmdConfig(ns string, dc doctl.Config, out io.Writer, args []string, init
c.ReservedIPActions = func() do.ReservedIPActionsService { return do.NewReservedIPActionsService(godoClient) }
c.Droplets = func() do.DropletsService { return do.NewDropletsService(godoClient) }
c.DropletActions = func() do.DropletActionsService { return do.NewDropletActionsService(godoClient) }
c.DropletAutoscale = func() do.DropletAutoscaleService { return do.NewDropletAutoscaleService(godoClient) }
c.Domains = func() do.DomainsService { return do.NewDomainsService(godoClient) }
c.Actions = func() do.ActionsService { return do.NewActionsService(godoClient) }
c.Account = func() do.AccountService { return do.NewAccountService(godoClient) }
Expand Down
3 changes: 3 additions & 0 deletions commands/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ type tcMocks struct {
billingHistory *domocks.MockBillingHistoryService
databases *domocks.MockDatabasesService
dropletActions *domocks.MockDropletActionsService
dropletAutoscale *domocks.MockDropletAutoscaleService
droplets *domocks.MockDropletsService
keys *domocks.MockKeysService
sizes *domocks.MockSizesService
Expand Down Expand Up @@ -206,6 +207,7 @@ func withTestClient(t *testing.T, tFn testFn) {
reservedIPActions: domocks.NewMockReservedIPActionsService(ctrl),
droplets: domocks.NewMockDropletsService(ctrl),
dropletActions: domocks.NewMockDropletActionsService(ctrl),
dropletAutoscale: domocks.NewMockDropletAutoscaleService(ctrl),
domains: domocks.NewMockDomainsService(ctrl),
tags: domocks.NewMockTagsService(ctrl),
uptimeChecks: domocks.NewMockUptimeChecksService(ctrl),
Expand Down Expand Up @@ -260,6 +262,7 @@ func withTestClient(t *testing.T, tFn testFn) {
ReservedIPActions: func() do.ReservedIPActionsService { return tm.reservedIPActions },
Droplets: func() do.DropletsService { return tm.droplets },
DropletActions: func() do.DropletActionsService { return tm.dropletActions },
DropletAutoscale: func() do.DropletAutoscaleService { return tm.dropletAutoscale },
Domains: func() do.DomainsService { return tm.domains },
Actions: func() do.ActionsService { return tm.actions },
Account: func() do.AccountService { return tm.account },
Expand Down
173 changes: 173 additions & 0 deletions commands/displayers/droplet_autoscale.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package displayers

import (
"io"

"github.com/digitalocean/godo"
)

type DropletAutoscalePools struct {
AutoscalePools []*godo.DropletAutoscalePool `json:"autoscale_pools"`
}

var _ Displayable = &DropletAutoscalePools{}

func (d *DropletAutoscalePools) Cols() []string {
return []string{
"ID",
"Name",
"Region",
"Status",
"Min Instance",
"Max Instance",
"Target Instance",
"Avg CPU Util",
"Avg Mem Util",
"Target CPU Util",
"Target Mem Util",
}
}

func (d *DropletAutoscalePools) ColMap() map[string]string {
return map[string]string{
"ID": "ID",
"Name": "Name",
"Region": "Region",
"Status": "Status",
"Min Instance": "Min Instance",
"Max Instance": "Max Instance",
"Target Instance": "Target Instance",
"Avg CPU Util": "Avg CPU Util",
"Avg Mem Util": "Avg Mem Util",
"Target CPU Util": "Target CPU Util",
"Target Mem Util": "Target Mem Util",
}
}

func (d *DropletAutoscalePools) KV() []map[string]any {
out := make([]map[string]any, 0, len(d.AutoscalePools))
for _, pool := range d.AutoscalePools {
var cpuUtil, memUtil any
if pool.CurrentUtilization != nil {
cpuUtil = pool.CurrentUtilization.CPU
memUtil = pool.CurrentUtilization.Memory
}
out = append(out, map[string]any{
"ID": pool.ID,
"Name": pool.Name,
"Region": pool.DropletTemplate.Region,
"Status": pool.Status,
"Min Instance": pool.Config.MinInstances,
"Max Instance": pool.Config.MaxInstances,
"Target Instance": pool.Config.TargetNumberInstances,
"Avg CPU Util": cpuUtil,
"Avg Mem Util": memUtil,
"Target CPU Util": pool.Config.TargetCPUUtilization,
"Target Mem Util": pool.Config.TargetMemoryUtilization,
})
}
return out
}

func (d *DropletAutoscalePools) JSON(out io.Writer) error {
return writeJSON(d.AutoscalePools, out)
}

type DropletAutoscaleResources struct {
Droplets []*godo.DropletAutoscaleResource `json:"droplets"`
}

var _ Displayable = &DropletAutoscaleResources{}

func (d *DropletAutoscaleResources) Cols() []string {
return []string{
"ID",
"Status",
"Health Status",
"Unhealthy Reason",
"CPU Util",
"Mem Util",
}
}

func (d *DropletAutoscaleResources) ColMap() map[string]string {
return map[string]string{
"ID": "ID",
"Status": "Status",
"Health Status": "Health Status",
"Unhealthy Reason": "Unhealthy Reason",
"CPU Util": "CPU Util",
"Mem Util": "Mem Util",
}
}

func (d *DropletAutoscaleResources) KV() []map[string]any {
out := make([]map[string]any, 0, len(d.Droplets))
for _, droplet := range d.Droplets {
var cpuUtil, memUtil any
if droplet.CurrentUtilization != nil {
cpuUtil = droplet.CurrentUtilization.CPU
memUtil = droplet.CurrentUtilization.Memory
}
out = append(out, map[string]any{
"ID": droplet.DropletID,
"Status": droplet.Status,
"Health Status": droplet.HealthStatus,
"Unhealthy Reason": droplet.UnhealthyReason,
"CPU Util": cpuUtil,
"Mem Util": memUtil,
})
}
return out
}

func (d *DropletAutoscaleResources) JSON(out io.Writer) error {
return writeJSON(d.Droplets, out)
}

type DropletAutoscaleHistoryEvents struct {
History []*godo.DropletAutoscaleHistoryEvent `json:"history"`
}

var _ Displayable = &DropletAutoscaleHistoryEvents{}

func (d *DropletAutoscaleHistoryEvents) Cols() []string {
return []string{
"ID",
"Current Instance",
"Target Instance",
"Status",
"Reason",
"Error Reason",
}
}

func (d *DropletAutoscaleHistoryEvents) ColMap() map[string]string {
return map[string]string{
"ID": "ID",
"Current Instance": "Current Instance",
"Target Instance": "Target Instance",
"Status": "Status",
"Reason": "Reason",
"Error Reason": "Error Reason",
}
}

func (d *DropletAutoscaleHistoryEvents) KV() []map[string]any {
out := make([]map[string]any, 0, len(d.History))
for _, history := range d.History {
out = append(out, map[string]any{
"ID": history.HistoryEventID,
"Current Instance": history.CurrentInstanceCount,
"Target Instance": history.DesiredInstanceCount,
"Status": history.Status,
"Reason": history.Reason,
"Error Reason": history.ErrorReason,
})
}
return out
}

func (d *DropletAutoscaleHistoryEvents) JSON(out io.Writer) error {
return writeJSON(d.History, out)
}
1 change: 1 addition & 0 deletions commands/doit.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func computeCmd() *Command {
cmd.AddCommand(Certificate())
cmd.AddCommand(DropletAction())
cmd.AddCommand(Droplet())
cmd.AddCommand(DropletAutoscale())
cmd.AddCommand(Domain())
cmd.AddCommand(Firewall())
cmd.AddCommand(ReservedIP())
Expand Down
Loading

0 comments on commit fbf093f

Please sign in to comment.