From fbf093f2060b6036f7c0e3fd20596b5d87c5d1d6 Mon Sep 17 00:00:00 2001 From: Aditya Saha Date: Fri, 15 Nov 2024 15:28:33 -0500 Subject: [PATCH] Introduce support for droplet autoscaler (#1606) * 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 --- args.go | 18 ++ commands/command_config.go | 2 + commands/commands_test.go | 3 + commands/displayers/droplet_autoscale.go | 173 +++++++++++ commands/doit.go | 1 + commands/droplet_autoscale.go | 373 +++++++++++++++++++++++ commands/droplet_autoscale_test.go | 224 ++++++++++++++ commands/load_balancers.go | 2 - do/droplet_autoscale.go | 152 +++++++++ do/mocks/AccountService.go | 1 + do/mocks/ActionService.go | 1 + do/mocks/AppsService.go | 1 + do/mocks/BalanceService.go | 1 + do/mocks/BillingHistoryService.go | 1 + do/mocks/CDNsService.go | 1 + do/mocks/CertificatesService.go | 1 + do/mocks/DatabasesService.go | 1 + do/mocks/DomainService.go | 1 + do/mocks/DropletActionService.go | 1 + do/mocks/DropletAutoscaleService.go | 159 ++++++++++ do/mocks/FirewallsService.go | 1 + do/mocks/ImageActionsService.go | 1 + do/mocks/ImageService.go | 1 + do/mocks/InvoicesService.go | 1 + do/mocks/KeysService.go | 1 + do/mocks/KubernetesService.go | 1 + do/mocks/Listen.go | 1 + do/mocks/LoadBalancersService.go | 1 + do/mocks/MonitoringService.go | 1 + do/mocks/OAuthService.go | 1 + do/mocks/OneClickService.go | 1 + do/mocks/ProjectsService.go | 1 + do/mocks/RegionsService.go | 1 + do/mocks/RegistryService.go | 1 + do/mocks/ReservedIPActionsService.go | 1 + do/mocks/ReservedIPsService.go | 1 + do/mocks/Runner.go | 1 + do/mocks/ServerlessService.go | 1 + do/mocks/SizesService.go | 1 + do/mocks/SnapshotsService.go | 1 + do/mocks/TagsService.go | 1 + do/mocks/UptimeChecksService.go | 1 + do/mocks/VPCsService.go | 1 + do/mocks/VolumeActionsService.go | 1 + do/mocks/VolumesService.go | 1 + scripts/regenmocks.sh | 1 + 46 files changed, 1141 insertions(+), 2 deletions(-) create mode 100644 commands/displayers/droplet_autoscale.go create mode 100644 commands/droplet_autoscale.go create mode 100644 commands/droplet_autoscale_test.go create mode 100644 do/droplet_autoscale.go create mode 100644 do/mocks/DropletAutoscaleService.go diff --git a/args.go b/args.go index 4b5290bb1..c651f3394 100644 --- a/args.go +++ b/args.go @@ -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. diff --git a/commands/command_config.go b/commands/command_config.go index 943e7df0d..91fe3d8a5 100644 --- a/commands/command_config.go +++ b/commands/command_config.go @@ -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 @@ -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) } diff --git a/commands/commands_test.go b/commands/commands_test.go index 0991468ec..1837453f8 100644 --- a/commands/commands_test.go +++ b/commands/commands_test.go @@ -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 @@ -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), @@ -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 }, diff --git a/commands/displayers/droplet_autoscale.go b/commands/displayers/droplet_autoscale.go new file mode 100644 index 000000000..f57501085 --- /dev/null +++ b/commands/displayers/droplet_autoscale.go @@ -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) +} diff --git a/commands/doit.go b/commands/doit.go index 4a2d3ef01..4ab3e66c1 100644 --- a/commands/doit.go +++ b/commands/doit.go @@ -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()) diff --git a/commands/droplet_autoscale.go b/commands/droplet_autoscale.go new file mode 100644 index 000000000..31b30c13a --- /dev/null +++ b/commands/droplet_autoscale.go @@ -0,0 +1,373 @@ +/* +Copyright 2018 The Doctl Authors All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package commands + +import ( + "strconv" + + "github.com/digitalocean/doctl" + "github.com/digitalocean/doctl/commands/displayers" + "github.com/digitalocean/godo" + "github.com/spf13/cobra" +) + +func DropletAutoscale() *Command { + cmd := &Command{ + Command: &cobra.Command{ + Hidden: true, + Use: "droplet-autoscale", + Aliases: []string{"das"}, + Short: "Display commands to manage Droplet autoscale pools", + Long: `Use the subcommands of ` + "`" + `doctl compute droplet-autoscale` + "`" + ` to perform actions on Droplet Autoscale Pools. + +You can use droplet-autoscale to perform CRUD operations on a Droplet Autoscale Pools.`, + }, + } + cmdDropletAutoscaleCreate := CmdBuilder(cmd, RunDropletAutoscaleCreate, "create", "Create a new Droplet autoscale pool", "", Writer, displayerType(&displayers.DropletAutoscalePools{})) + + cmdDropletAutoscaleUpdate := CmdBuilder(cmd, RunDropletAutoscaleUpdate, "update ", "Update an active Droplet autoscale pool", "", Writer, displayerType(&displayers.DropletAutoscalePools{})) + + for _, c := range []*Command{ + cmdDropletAutoscaleCreate, + cmdDropletAutoscaleUpdate, + } { + AddStringFlag(c, doctl.ArgAutoscaleName, "", "", "Name of the Droplet autoscale pool", requiredOpt()) + AddIntFlag(c, doctl.ArgAutoscaleMinInstances, "", 0, "Min number of members") + AddIntFlag(c, doctl.ArgAutoscaleMaxInstances, "", 0, "Max number of members") + AddStringFlag(c, doctl.ArgAutoscaleCpuTarget, "", "", "CPU target threshold") + AddStringFlag(c, doctl.ArgAutoscaleMemTarget, "", "", "Memory target threshold") + AddIntFlag(c, doctl.ArgAutoscaleCooldownMinutes, "", 0, "Cooldown duration") + AddIntFlag(c, doctl.ArgAutoscaleTargetInstances, "", 0, "Target number of members") + + AddStringFlag(c, doctl.ArgSizeSlug, "", "", "Droplet size") + AddStringFlag(c, doctl.ArgRegionSlug, "", "", "Droplet region") + AddStringFlag(c, doctl.ArgImage, "", "", "Droplet image") + AddStringSliceFlag(c, doctl.ArgTag, "", []string{}, "Droplet tags") + AddStringSliceFlag(c, doctl.ArgSSHKeys, "", []string{}, "Droplet SSH keys") + AddStringFlag(c, doctl.ArgVPCUUID, "", "", "Droplet VPC UUID") + AddBoolFlag(c, doctl.ArgDropletAgent, "", true, "Enable droplet agent") + AddStringFlag(c, doctl.ArgProjectID, "", "", "Droplet project ID") + AddBoolFlag(c, doctl.ArgIPv6, "", true, "Enable droplet IPv6") + AddStringFlag(c, doctl.ArgUserData, "", "", "Droplet user data") + } + + CmdBuilder(cmd, RunDropletAutoscaleGet, "get ", "Get an active Droplet autoscale pool", "", Writer, displayerType(&displayers.DropletAutoscalePools{})) + + CmdBuilder(cmd, RunDropletAutoscaleList, "list", "List all active Droplet autoscale pools", "", Writer, displayerType(&displayers.DropletAutoscalePools{}), aliasOpt("ls")) + + CmdBuilder(cmd, RunDropletAutoscaleListMembers, "list-members ", "List all members of a Droplet autoscale pool", "", Writer, displayerType(&displayers.DropletAutoscaleResources{})) + + CmdBuilder(cmd, RunDropletAutoscaleListHistory, "list-history ", "List all history events for a Droplet autoscale pool", "", Writer, displayerType(&displayers.DropletAutoscaleHistoryEvents{})) + + cmdDropletAutoscaleDelete := CmdBuilder(cmd, RunDropletAutoscaleDelete, "delete ", "Delete an active Droplet autoscale pool", "", Writer, aliasOpt("d", "rm")) + AddBoolFlag(cmdDropletAutoscaleDelete, doctl.ArgForce, "", false, "Force delete without a confirmation prompt") + + cmdDropletAutoscaleDeleteDangerous := CmdBuilder(cmd, RunDropletAutoscaleDeleteDangerous, "delete-dangerous ", "Delete an active Droplet autoscale pool and all its members", "", Writer) + AddBoolFlag(cmdDropletAutoscaleDeleteDangerous, doctl.ArgForce, "", false, "Force delete without a confirmation prompt") + + return cmd +} + +func buildDropletAutoscaleRequestFromArgs(c *CmdConfig, r *godo.DropletAutoscalePoolRequest) error { + var hydrators = []func() error{ + func() error { + name, err := c.Doit.GetString(c.NS, doctl.ArgAutoscaleName) + if err != nil { + return err + } + r.Name = name + return nil + }, + func() error { + minCount, err := c.Doit.GetInt(c.NS, doctl.ArgAutoscaleMinInstances) + if err != nil { + return err + } + r.Config.MinInstances = uint64(minCount) + return nil + }, + func() error { + maxCount, err := c.Doit.GetInt(c.NS, doctl.ArgAutoscaleMaxInstances) + if err != nil { + return err + } + r.Config.MaxInstances = uint64(maxCount) + return nil + }, + func() error { + cpuStr, err := c.Doit.GetString(c.NS, doctl.ArgAutoscaleCpuTarget) + if err != nil { + return err + } + if cpuStr != "" { + cpuTarget, err := strconv.ParseFloat(cpuStr, 64) + if err != nil { + return err + } + r.Config.TargetCPUUtilization = cpuTarget + } + return nil + }, + func() error { + memStr, err := c.Doit.GetString(c.NS, doctl.ArgAutoscaleMemTarget) + if err != nil { + return err + } + if memStr != "" { + memTarget, err := strconv.ParseFloat(memStr, 64) + if err != nil { + return err + } + r.Config.TargetMemoryUtilization = memTarget + } + return nil + }, + func() error { + cooldown, err := c.Doit.GetInt(c.NS, doctl.ArgAutoscaleCooldownMinutes) + if err != nil { + return err + } + r.Config.CooldownMinutes = uint32(cooldown) + return nil + }, + func() error { + targetCount, err := c.Doit.GetInt(c.NS, doctl.ArgAutoscaleTargetInstances) + if err != nil { + return err + } + r.Config.TargetNumberInstances = uint64(targetCount) + return nil + }, + func() error { + size, err := c.Doit.GetString(c.NS, doctl.ArgSizeSlug) + if err != nil { + return err + } + r.DropletTemplate.Size = size + return nil + }, + func() error { + region, err := c.Doit.GetString(c.NS, doctl.ArgRegionSlug) + if err != nil { + return err + } + r.DropletTemplate.Region = region + return nil + }, + func() error { + image, err := c.Doit.GetString(c.NS, doctl.ArgImage) + if err != nil { + return err + } + r.DropletTemplate.Image = image + return nil + }, + func() error { + tags, err := c.Doit.GetStringSlice(c.NS, doctl.ArgTag) + if err != nil { + return err + } + r.DropletTemplate.Tags = tags + return nil + }, + func() error { + sshKeys, err := c.Doit.GetStringSlice(c.NS, doctl.ArgSSHKeys) + if err != nil { + return err + } + r.DropletTemplate.SSHKeys = sshKeys + return nil + }, + func() error { + vpcUUID, err := c.Doit.GetString(c.NS, doctl.ArgVPCUUID) + if err != nil { + return err + } + r.DropletTemplate.VpcUUID = vpcUUID + return nil + }, + func() error { + enableAgent, err := c.Doit.GetBool(c.NS, doctl.ArgDropletAgent) + if err != nil { + return err + } + r.DropletTemplate.WithDropletAgent = enableAgent + return nil + }, + func() error { + projectID, err := c.Doit.GetString(c.NS, doctl.ArgProjectID) + if err != nil { + return err + } + r.DropletTemplate.ProjectID = projectID + return nil + }, + func() error { + enableIPv6, err := c.Doit.GetBool(c.NS, doctl.ArgIPv6) + if err != nil { + return err + } + r.DropletTemplate.IPV6 = enableIPv6 + return nil + }, + func() error { + userData, err := c.Doit.GetString(c.NS, doctl.ArgUserData) + if err != nil { + return err + } + r.DropletTemplate.UserData = userData + return nil + }, + } + for _, h := range hydrators { + if err := h(); err != nil { + return err + } + } + return nil +} + +// RunDropletAutoscaleCreate creates an autoscale pool +func RunDropletAutoscaleCreate(c *CmdConfig) error { + createReq := new(godo.DropletAutoscalePoolRequest) + createReq.Config = new(godo.DropletAutoscaleConfiguration) + createReq.DropletTemplate = new(godo.DropletAutoscaleResourceTemplate) + if err := buildDropletAutoscaleRequestFromArgs(c, createReq); err != nil { + return err + } + pool, err := c.DropletAutoscale().Create(createReq) + if err != nil { + return err + } + item := &displayers.DropletAutoscalePools{AutoscalePools: []*godo.DropletAutoscalePool{pool}} + return c.Display(item) +} + +// RunDropletAutoscaleUpdate updates an autoscale pool +func RunDropletAutoscaleUpdate(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + updateReq := new(godo.DropletAutoscalePoolRequest) + updateReq.Config = new(godo.DropletAutoscaleConfiguration) + updateReq.DropletTemplate = new(godo.DropletAutoscaleResourceTemplate) + if err := buildDropletAutoscaleRequestFromArgs(c, updateReq); err != nil { + return err + } + pool, err := c.DropletAutoscale().Update(id, updateReq) + if err != nil { + return err + } + item := &displayers.DropletAutoscalePools{AutoscalePools: []*godo.DropletAutoscalePool{pool}} + return c.Display(item) +} + +// RunDropletAutoscaleGet retrieves an autoscale pool +func RunDropletAutoscaleGet(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + pool, err := c.DropletAutoscale().Get(id) + if err != nil { + return err + } + item := &displayers.DropletAutoscalePools{AutoscalePools: []*godo.DropletAutoscalePool{pool}} + return c.Display(item) +} + +// RunDropletAutoscaleList lists all autoscale pools +func RunDropletAutoscaleList(c *CmdConfig) error { + pools, err := c.DropletAutoscale().List() + if err != nil { + return err + } + item := &displayers.DropletAutoscalePools{AutoscalePools: pools} + return c.Display(item) +} + +// RunDropletAutoscaleListMembers lists autoscale pool members +func RunDropletAutoscaleListMembers(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + members, err := c.DropletAutoscale().ListMembers(id) + if err != nil { + return err + } + item := &displayers.DropletAutoscaleResources{Droplets: members} + return c.Display(item) +} + +// RunDropletAutoscaleListHistory lists autoscale pool history events +func RunDropletAutoscaleListHistory(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + history, err := c.DropletAutoscale().ListHistory(id) + if err != nil { + return err + } + item := &displayers.DropletAutoscaleHistoryEvents{History: history} + return c.Display(item) +} + +// RunDropletAutoscaleDelete deletes an autoscale pool +func RunDropletAutoscaleDelete(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + force, err := c.Doit.GetBool(c.NS, doctl.ArgForce) + if err != nil { + return err + } + if force || AskForConfirmDelete("droplet autoscale pool", 1) == nil { + if err = c.DropletAutoscale().Delete(id); err != nil { + return err + } + } else { + return errOperationAborted + } + return nil +} + +// RunDropletAutoscaleDeleteDangerous deletes an autoscale pool and all underlying members +func RunDropletAutoscaleDeleteDangerous(c *CmdConfig) error { + err := ensureOneArg(c) + if err != nil { + return err + } + id := c.Args[0] + force, err := c.Doit.GetBool(c.NS, doctl.ArgForce) + if err != nil { + return err + } + if force || AskForConfirmDelete("droplet autoscale pool", 1) == nil { + if err = c.DropletAutoscale().DeleteDangerous(id); err != nil { + return err + } + } else { + return errOperationAborted + } + return nil +} diff --git a/commands/droplet_autoscale_test.go b/commands/droplet_autoscale_test.go new file mode 100644 index 000000000..b9d08b66d --- /dev/null +++ b/commands/droplet_autoscale_test.go @@ -0,0 +1,224 @@ +package commands + +import ( + "testing" + + "github.com/digitalocean/doctl" + "github.com/digitalocean/godo" + "github.com/stretchr/testify/assert" +) + +var ( + testAutoscalePools = []*godo.DropletAutoscalePool{ + { + ID: "51154959-e07b-4093-98fb-828590ecc76d", + Name: "test-droplet-autoscale-pool-01", + Config: &godo.DropletAutoscaleConfiguration{ + TargetNumberInstances: 3, + }, + DropletTemplate: &godo.DropletAutoscaleResourceTemplate{ + Size: "s-1vcpu-512mb-10gb", + Region: "s2r1", + Image: "547864", + Tags: []string{"test-pool-01"}, + SSHKeys: []string{"key-1", "key-2"}, + VpcUUID: "05790d02-c7e0-47d6-a917-5b4cf68cf5b7", + WithDropletAgent: true, + UserData: "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n", + }, + }, + { + ID: "4d99fb28-b33d-4791-aff5-bf30f8f4f917", + Name: "test-droplet-autoscale-pool-02", + Config: &godo.DropletAutoscaleConfiguration{ + TargetNumberInstances: 3, + }, + DropletTemplate: &godo.DropletAutoscaleResourceTemplate{ + Size: "s-1vcpu-512mb-10gb", + Region: "s2r1", + Image: "547864", + Tags: []string{"test-pool-02"}, + SSHKeys: []string{"key-1", "key-2"}, + VpcUUID: "05790d02-c7e0-47d6-a917-5b4cf68cf5b7", + WithDropletAgent: true, + UserData: "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n", + }, + }, + } + testAutoscaleMembers = []*godo.DropletAutoscaleResource{ + { + DropletID: 1, + HealthStatus: "healthy", + Status: "active", + }, + { + DropletID: 2, + HealthStatus: "healthy", + Status: "active", + }, + } + testAutoscaleHistory = []*godo.DropletAutoscaleHistoryEvent{ + { + HistoryEventID: "c4686a63-4996-484d-b269-b329b7e97051", + CurrentInstanceCount: 0, + DesiredInstanceCount: 3, + Reason: "configuration update", + Status: "success", + }, + { + HistoryEventID: "cb676933-73ba-43da-9c43-bb286a5af545", + CurrentInstanceCount: 3, + DesiredInstanceCount: 3, + Reason: "scale up", + Status: "success", + }, + } +) + +func TestDropletAutoscaleCommand(t *testing.T) { + cmd := DropletAutoscale() + assert.NotNil(t, cmd) + assertCommandNames(t, cmd, "create", "update", "get", "list", "list-members", "list-history", "delete", "delete-dangerous") +} + +func TestDropletAutoscaleCreate(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + createReq := godo.DropletAutoscalePoolRequest{ + Name: "test-droplet-autoscale-pool-01", + Config: &godo.DropletAutoscaleConfiguration{ + TargetNumberInstances: 3, + }, + DropletTemplate: &godo.DropletAutoscaleResourceTemplate{ + Size: "s-1vcpu-512mb-10gb", + Region: "s2r1", + Image: "547864", + Tags: []string{"test-pool-01"}, + SSHKeys: []string{"key-1", "key-2"}, + VpcUUID: "05790d02-c7e0-47d6-a917-5b4cf68cf5b7", + WithDropletAgent: true, + UserData: "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n", + }, + } + + tm.dropletAutoscale.EXPECT().Create(&createReq).Return(testAutoscalePools[0], nil) + + c.Doit.Set(c.NS, doctl.ArgAutoscaleName, "test-droplet-autoscale-pool-01") + c.Doit.Set(c.NS, doctl.ArgAutoscaleTargetInstances, "3") + c.Doit.Set(c.NS, doctl.ArgSizeSlug, "s-1vcpu-512mb-10gb") + c.Doit.Set(c.NS, doctl.ArgRegionSlug, "s2r1") + c.Doit.Set(c.NS, doctl.ArgImage, "547864") + c.Doit.Set(c.NS, doctl.ArgTag, "test-pool-01") + c.Doit.Set(c.NS, doctl.ArgSSHKeys, []string{"key-1", "key-2"}) + c.Doit.Set(c.NS, doctl.ArgVPCUUID, "05790d02-c7e0-47d6-a917-5b4cf68cf5b7") + c.Doit.Set(c.NS, doctl.ArgDropletAgent, "true") + c.Doit.Set(c.NS, doctl.ArgUserData, "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n") + + err := RunDropletAutoscaleCreate(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleUpdate(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + updateReq := godo.DropletAutoscalePoolRequest{ + Name: "test-droplet-autoscale-pool-01", + Config: &godo.DropletAutoscaleConfiguration{ + TargetNumberInstances: 3, + }, + DropletTemplate: &godo.DropletAutoscaleResourceTemplate{ + Size: "s-1vcpu-512mb-10gb", + Region: "s2r1", + Image: "547864", + Tags: []string{"test-pool-01"}, + SSHKeys: []string{"key-1", "key-2"}, + VpcUUID: "05790d02-c7e0-47d6-a917-5b4cf68cf5b7", + WithDropletAgent: true, + UserData: "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n", + }, + } + + tm.dropletAutoscale.EXPECT().Update(poolID, &updateReq).Return(testAutoscalePools[0], nil) + c.Args = append(c.Args, poolID) + + c.Doit.Set(c.NS, doctl.ArgAutoscaleName, "test-droplet-autoscale-pool-01") + c.Doit.Set(c.NS, doctl.ArgAutoscaleTargetInstances, "3") + c.Doit.Set(c.NS, doctl.ArgSizeSlug, "s-1vcpu-512mb-10gb") + c.Doit.Set(c.NS, doctl.ArgRegionSlug, "s2r1") + c.Doit.Set(c.NS, doctl.ArgImage, "547864") + c.Doit.Set(c.NS, doctl.ArgTag, "test-pool-01") + c.Doit.Set(c.NS, doctl.ArgSSHKeys, []string{"key-1", "key-2"}) + c.Doit.Set(c.NS, doctl.ArgVPCUUID, "05790d02-c7e0-47d6-a917-5b4cf68cf5b7") + c.Doit.Set(c.NS, doctl.ArgDropletAgent, "true") + c.Doit.Set(c.NS, doctl.ArgUserData, "\n#cloud-config\nruncmd:\n- apt-get update\n- apt-get install -y stress-ng\n") + + err := RunDropletAutoscaleUpdate(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleGet(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + tm.dropletAutoscale.EXPECT().Get(poolID).Return(testAutoscalePools[0], nil) + c.Args = append(c.Args, poolID) + + err := RunDropletAutoscaleGet(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleList(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + tm.dropletAutoscale.EXPECT().List().Return(testAutoscalePools, nil) + + err := RunDropletAutoscaleList(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleListMembers(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + tm.dropletAutoscale.EXPECT().ListMembers(poolID).Return(testAutoscaleMembers, nil) + c.Args = append(c.Args, poolID) + + err := RunDropletAutoscaleListMembers(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleListHistory(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + tm.dropletAutoscale.EXPECT().ListHistory(poolID).Return(testAutoscaleHistory, nil) + c.Args = append(c.Args, poolID) + + err := RunDropletAutoscaleListHistory(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleDelete(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + tm.dropletAutoscale.EXPECT().Delete(poolID).Return(nil) + c.Args = append(c.Args, poolID) + c.Doit.Set(c.NS, doctl.ArgForce, "true") + + err := RunDropletAutoscaleDelete(c) + assert.NoError(t, err) + }) +} + +func TestDropletAutoscaleDeleteDangerous(t *testing.T) { + withTestClient(t, func(c *CmdConfig, tm *tcMocks) { + poolID := "51154959-e07b-4093-98fb-828590ecc76d" + tm.dropletAutoscale.EXPECT().DeleteDangerous(poolID).Return(nil) + c.Args = append(c.Args, poolID) + c.Doit.Set(c.NS, doctl.ArgForce, "true") + + err := RunDropletAutoscaleDeleteDangerous(c) + assert.NoError(t, err) + }) +} diff --git a/commands/load_balancers.go b/commands/load_balancers.go index bc648eaad..ce562fbfb 100644 --- a/commands/load_balancers.go +++ b/commands/load_balancers.go @@ -101,8 +101,6 @@ With the load-balancer command, you can list, create, or delete load balancers, AddStringSliceFlag(cmdLoadBalancerCreate, doctl.ArgTargetLoadBalancerIDs, "", []string{}, "A comma-separated list of Load Balancer IDs to add as target to the global load balancer ") AddStringFlag(cmdLoadBalancerCreate, doctl.ArgLoadBalancerNetwork, "", "", "The type of network the load balancer is accessible from, e.g.: `EXTERNAL` or `INTERNAL`") - cmdLoadBalancerCreate.Flags().MarkHidden(doctl.ArgLoadBalancerType) - cmdLoadBalancerCreate.Flags().MarkHidden(doctl.ArgLoadBalancerNetwork) cmdRecordUpdate := CmdBuilder(cmd, RunLoadBalancerUpdate, "update ", "Update a load balancer's configuration", `Use this command to update the configuration of a specified load balancer. Using all applicable flags, the command should contain a full representation of the load balancer including existing attributes, such as the load balancer's name, region, forwarding rules, and Droplet IDs. Any attribute that is not provided is reset to its default value.`, Writer, aliasOpt("u")) diff --git a/do/droplet_autoscale.go b/do/droplet_autoscale.go new file mode 100644 index 000000000..5eaefee69 --- /dev/null +++ b/do/droplet_autoscale.go @@ -0,0 +1,152 @@ +/* +Copyright 2018 The Doctl Authors All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package do + +import ( + "context" + + "github.com/digitalocean/godo" +) + +type DropletAutoscaleService interface { + Create(*godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) + Get(string) (*godo.DropletAutoscalePool, error) + List() ([]*godo.DropletAutoscalePool, error) + ListMembers(string) ([]*godo.DropletAutoscaleResource, error) + ListHistory(string) ([]*godo.DropletAutoscaleHistoryEvent, error) + Update(string, *godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) + Delete(string) error + DeleteDangerous(string) error +} + +var _ DropletAutoscaleService = &dropletAutoscaleService{} + +type dropletAutoscaleService struct { + client *godo.Client +} + +// NewDropletAutoscaleService creates an instance of DropletAutoscaleService +func NewDropletAutoscaleService(client *godo.Client) DropletAutoscaleService { + return &dropletAutoscaleService{ + client: client, + } +} + +// Create creates a new droplet autoscale pool +func (d *dropletAutoscaleService) Create(createReq *godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) { + pool, _, err := d.client.DropletAutoscale.Create(context.Background(), createReq) + if err != nil { + return nil, err + } + return pool, nil +} + +// Get retrieves an existing droplet autoscale pool +func (d *dropletAutoscaleService) Get(poolID string) (*godo.DropletAutoscalePool, error) { + pool, _, err := d.client.DropletAutoscale.Get(context.Background(), poolID) + if err != nil { + return nil, err + } + return pool, nil +} + +// List lists all existing droplet autoscale pools +func (d *dropletAutoscaleService) List() ([]*godo.DropletAutoscalePool, error) { + listResp, err := PaginateResp(func(opts *godo.ListOptions) ([]any, *godo.Response, error) { + pools, resp, err := d.client.DropletAutoscale.List(context.Background(), opts) + if err != nil { + return nil, nil, err + } + anyResp := make([]any, 0, len(pools)) + for _, pool := range pools { + anyResp = append(anyResp, pool) + } + return anyResp, resp, err + }) + if err != nil { + return nil, err + } + pools := make([]*godo.DropletAutoscalePool, 0, len(listResp)) + for _, pool := range listResp { + pools = append(pools, pool.(*godo.DropletAutoscalePool)) + } + return pools, nil +} + +// ListMembers lists all droplet autoscale resources for an existing pool +func (d *dropletAutoscaleService) ListMembers(poolID string) ([]*godo.DropletAutoscaleResource, error) { + listResp, err := PaginateResp(func(opts *godo.ListOptions) ([]any, *godo.Response, error) { + members, resp, err := d.client.DropletAutoscale.ListMembers(context.Background(), poolID, opts) + if err != nil { + return nil, nil, err + } + anyResp := make([]any, 0, len(members)) + for _, member := range members { + anyResp = append(anyResp, member) + } + return anyResp, resp, err + }) + if err != nil { + return nil, err + } + members := make([]*godo.DropletAutoscaleResource, 0, len(listResp)) + for _, member := range listResp { + members = append(members, member.(*godo.DropletAutoscaleResource)) + } + return members, nil +} + +// ListHistory lists all droplet autoscale history events for an existing pool +func (d *dropletAutoscaleService) ListHistory(poolID string) ([]*godo.DropletAutoscaleHistoryEvent, error) { + listResp, err := PaginateResp(func(opts *godo.ListOptions) ([]any, *godo.Response, error) { + events, resp, err := d.client.DropletAutoscale.ListHistory(context.Background(), poolID, opts) + if err != nil { + return nil, nil, err + } + anyResp := make([]any, 0, len(events)) + for _, event := range events { + anyResp = append(anyResp, event) + } + return anyResp, resp, err + }) + if err != nil { + return nil, err + } + events := make([]*godo.DropletAutoscaleHistoryEvent, 0, len(listResp)) + for _, event := range listResp { + events = append(events, event.(*godo.DropletAutoscaleHistoryEvent)) + } + return events, nil +} + +// Update updates an existing droplet autoscale pool +func (d *dropletAutoscaleService) Update(poolID string, updateReq *godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) { + pool, _, err := d.client.DropletAutoscale.Update(context.Background(), poolID, updateReq) + if err != nil { + return nil, err + } + return pool, nil +} + +// Delete deletes an existing droplet autoscale pool +func (d *dropletAutoscaleService) Delete(poolID string) error { + _, err := d.client.DropletAutoscale.Delete(context.Background(), poolID) + return err +} + +// DeleteDangerous deletes an existing droplet autoscale pool and all its underlying resources +func (d *dropletAutoscaleService) DeleteDangerous(poolID string) error { + _, err := d.client.DropletAutoscale.DeleteDangerous(context.Background(), poolID) + return err +} diff --git a/do/mocks/AccountService.go b/do/mocks/AccountService.go index 2a98fcd08..53bbf828c 100644 --- a/do/mocks/AccountService.go +++ b/do/mocks/AccountService.go @@ -20,6 +20,7 @@ import ( type MockAccountService struct { ctrl *gomock.Controller recorder *MockAccountServiceMockRecorder + isgomock struct{} } // MockAccountServiceMockRecorder is the mock recorder for MockAccountService. diff --git a/do/mocks/ActionService.go b/do/mocks/ActionService.go index 8dbf872ff..d571cc942 100644 --- a/do/mocks/ActionService.go +++ b/do/mocks/ActionService.go @@ -20,6 +20,7 @@ import ( type MockActionsService struct { ctrl *gomock.Controller recorder *MockActionsServiceMockRecorder + isgomock struct{} } // MockActionsServiceMockRecorder is the mock recorder for MockActionsService. diff --git a/do/mocks/AppsService.go b/do/mocks/AppsService.go index c1f9421f6..f0774d7df 100644 --- a/do/mocks/AppsService.go +++ b/do/mocks/AppsService.go @@ -20,6 +20,7 @@ import ( type MockAppsService struct { ctrl *gomock.Controller recorder *MockAppsServiceMockRecorder + isgomock struct{} } // MockAppsServiceMockRecorder is the mock recorder for MockAppsService. diff --git a/do/mocks/BalanceService.go b/do/mocks/BalanceService.go index ea9a08ff4..81384906e 100644 --- a/do/mocks/BalanceService.go +++ b/do/mocks/BalanceService.go @@ -20,6 +20,7 @@ import ( type MockBalanceService struct { ctrl *gomock.Controller recorder *MockBalanceServiceMockRecorder + isgomock struct{} } // MockBalanceServiceMockRecorder is the mock recorder for MockBalanceService. diff --git a/do/mocks/BillingHistoryService.go b/do/mocks/BillingHistoryService.go index 79203d17b..65cf25228 100644 --- a/do/mocks/BillingHistoryService.go +++ b/do/mocks/BillingHistoryService.go @@ -20,6 +20,7 @@ import ( type MockBillingHistoryService struct { ctrl *gomock.Controller recorder *MockBillingHistoryServiceMockRecorder + isgomock struct{} } // MockBillingHistoryServiceMockRecorder is the mock recorder for MockBillingHistoryService. diff --git a/do/mocks/CDNsService.go b/do/mocks/CDNsService.go index d2aaf34cf..72cdc4514 100644 --- a/do/mocks/CDNsService.go +++ b/do/mocks/CDNsService.go @@ -21,6 +21,7 @@ import ( type MockCDNsService struct { ctrl *gomock.Controller recorder *MockCDNsServiceMockRecorder + isgomock struct{} } // MockCDNsServiceMockRecorder is the mock recorder for MockCDNsService. diff --git a/do/mocks/CertificatesService.go b/do/mocks/CertificatesService.go index 33cecdf0b..b4d42f4ad 100644 --- a/do/mocks/CertificatesService.go +++ b/do/mocks/CertificatesService.go @@ -21,6 +21,7 @@ import ( type MockCertificatesService struct { ctrl *gomock.Controller recorder *MockCertificatesServiceMockRecorder + isgomock struct{} } // MockCertificatesServiceMockRecorder is the mock recorder for MockCertificatesService. diff --git a/do/mocks/DatabasesService.go b/do/mocks/DatabasesService.go index b9f2a99c0..b36985a5c 100644 --- a/do/mocks/DatabasesService.go +++ b/do/mocks/DatabasesService.go @@ -21,6 +21,7 @@ import ( type MockDatabasesService struct { ctrl *gomock.Controller recorder *MockDatabasesServiceMockRecorder + isgomock struct{} } // MockDatabasesServiceMockRecorder is the mock recorder for MockDatabasesService. diff --git a/do/mocks/DomainService.go b/do/mocks/DomainService.go index ae1c24f49..1528b28d8 100644 --- a/do/mocks/DomainService.go +++ b/do/mocks/DomainService.go @@ -21,6 +21,7 @@ import ( type MockDomainsService struct { ctrl *gomock.Controller recorder *MockDomainsServiceMockRecorder + isgomock struct{} } // MockDomainsServiceMockRecorder is the mock recorder for MockDomainsService. diff --git a/do/mocks/DropletActionService.go b/do/mocks/DropletActionService.go index 0aacf090d..1141c5083 100644 --- a/do/mocks/DropletActionService.go +++ b/do/mocks/DropletActionService.go @@ -20,6 +20,7 @@ import ( type MockDropletActionsService struct { ctrl *gomock.Controller recorder *MockDropletActionsServiceMockRecorder + isgomock struct{} } // MockDropletActionsServiceMockRecorder is the mock recorder for MockDropletActionsService. diff --git a/do/mocks/DropletAutoscaleService.go b/do/mocks/DropletAutoscaleService.go new file mode 100644 index 000000000..3fa30c054 --- /dev/null +++ b/do/mocks/DropletAutoscaleService.go @@ -0,0 +1,159 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: droplet_autoscale.go +// +// Generated by this command: +// +// mockgen -source droplet_autoscale.go -package=mocks DropletAutoscaleService +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + godo "github.com/digitalocean/godo" + gomock "go.uber.org/mock/gomock" +) + +// MockDropletAutoscaleService is a mock of DropletAutoscaleService interface. +type MockDropletAutoscaleService struct { + ctrl *gomock.Controller + recorder *MockDropletAutoscaleServiceMockRecorder + isgomock struct{} +} + +// MockDropletAutoscaleServiceMockRecorder is the mock recorder for MockDropletAutoscaleService. +type MockDropletAutoscaleServiceMockRecorder struct { + mock *MockDropletAutoscaleService +} + +// NewMockDropletAutoscaleService creates a new mock instance. +func NewMockDropletAutoscaleService(ctrl *gomock.Controller) *MockDropletAutoscaleService { + mock := &MockDropletAutoscaleService{ctrl: ctrl} + mock.recorder = &MockDropletAutoscaleServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDropletAutoscaleService) EXPECT() *MockDropletAutoscaleServiceMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockDropletAutoscaleService) Create(arg0 *godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0) + ret0, _ := ret[0].(*godo.DropletAutoscalePool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockDropletAutoscaleServiceMockRecorder) Create(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockDropletAutoscaleService)(nil).Create), arg0) +} + +// Delete mocks base method. +func (m *MockDropletAutoscaleService) Delete(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockDropletAutoscaleServiceMockRecorder) Delete(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDropletAutoscaleService)(nil).Delete), arg0) +} + +// DeleteDangerous mocks base method. +func (m *MockDropletAutoscaleService) DeleteDangerous(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDangerous", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDangerous indicates an expected call of DeleteDangerous. +func (mr *MockDropletAutoscaleServiceMockRecorder) DeleteDangerous(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDangerous", reflect.TypeOf((*MockDropletAutoscaleService)(nil).DeleteDangerous), arg0) +} + +// Get mocks base method. +func (m *MockDropletAutoscaleService) Get(arg0 string) (*godo.DropletAutoscalePool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(*godo.DropletAutoscalePool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockDropletAutoscaleServiceMockRecorder) Get(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDropletAutoscaleService)(nil).Get), arg0) +} + +// List mocks base method. +func (m *MockDropletAutoscaleService) List() ([]*godo.DropletAutoscalePool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List") + ret0, _ := ret[0].([]*godo.DropletAutoscalePool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockDropletAutoscaleServiceMockRecorder) List() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockDropletAutoscaleService)(nil).List)) +} + +// ListHistory mocks base method. +func (m *MockDropletAutoscaleService) ListHistory(arg0 string) ([]*godo.DropletAutoscaleHistoryEvent, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListHistory", arg0) + ret0, _ := ret[0].([]*godo.DropletAutoscaleHistoryEvent) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListHistory indicates an expected call of ListHistory. +func (mr *MockDropletAutoscaleServiceMockRecorder) ListHistory(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListHistory", reflect.TypeOf((*MockDropletAutoscaleService)(nil).ListHistory), arg0) +} + +// ListMembers mocks base method. +func (m *MockDropletAutoscaleService) ListMembers(arg0 string) ([]*godo.DropletAutoscaleResource, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListMembers", arg0) + ret0, _ := ret[0].([]*godo.DropletAutoscaleResource) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListMembers indicates an expected call of ListMembers. +func (mr *MockDropletAutoscaleServiceMockRecorder) ListMembers(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMembers", reflect.TypeOf((*MockDropletAutoscaleService)(nil).ListMembers), arg0) +} + +// Update mocks base method. +func (m *MockDropletAutoscaleService) Update(arg0 string, arg1 *godo.DropletAutoscalePoolRequest) (*godo.DropletAutoscalePool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", arg0, arg1) + ret0, _ := ret[0].(*godo.DropletAutoscalePool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockDropletAutoscaleServiceMockRecorder) Update(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockDropletAutoscaleService)(nil).Update), arg0, arg1) +} diff --git a/do/mocks/FirewallsService.go b/do/mocks/FirewallsService.go index 8a318691c..28046e32d 100644 --- a/do/mocks/FirewallsService.go +++ b/do/mocks/FirewallsService.go @@ -21,6 +21,7 @@ import ( type MockFirewallsService struct { ctrl *gomock.Controller recorder *MockFirewallsServiceMockRecorder + isgomock struct{} } // MockFirewallsServiceMockRecorder is the mock recorder for MockFirewallsService. diff --git a/do/mocks/ImageActionsService.go b/do/mocks/ImageActionsService.go index 0ca645aa0..733c536f8 100644 --- a/do/mocks/ImageActionsService.go +++ b/do/mocks/ImageActionsService.go @@ -21,6 +21,7 @@ import ( type MockImageActionsService struct { ctrl *gomock.Controller recorder *MockImageActionsServiceMockRecorder + isgomock struct{} } // MockImageActionsServiceMockRecorder is the mock recorder for MockImageActionsService. diff --git a/do/mocks/ImageService.go b/do/mocks/ImageService.go index 4dacd4e2d..d8aa1ee5f 100644 --- a/do/mocks/ImageService.go +++ b/do/mocks/ImageService.go @@ -21,6 +21,7 @@ import ( type MockImagesService struct { ctrl *gomock.Controller recorder *MockImagesServiceMockRecorder + isgomock struct{} } // MockImagesServiceMockRecorder is the mock recorder for MockImagesService. diff --git a/do/mocks/InvoicesService.go b/do/mocks/InvoicesService.go index f7e2625f8..827f587d3 100644 --- a/do/mocks/InvoicesService.go +++ b/do/mocks/InvoicesService.go @@ -20,6 +20,7 @@ import ( type MockInvoicesService struct { ctrl *gomock.Controller recorder *MockInvoicesServiceMockRecorder + isgomock struct{} } // MockInvoicesServiceMockRecorder is the mock recorder for MockInvoicesService. diff --git a/do/mocks/KeysService.go b/do/mocks/KeysService.go index a4fd9002a..1a16868fa 100644 --- a/do/mocks/KeysService.go +++ b/do/mocks/KeysService.go @@ -21,6 +21,7 @@ import ( type MockKeysService struct { ctrl *gomock.Controller recorder *MockKeysServiceMockRecorder + isgomock struct{} } // MockKeysServiceMockRecorder is the mock recorder for MockKeysService. diff --git a/do/mocks/KubernetesService.go b/do/mocks/KubernetesService.go index 5ec1063c7..d4b44e985 100644 --- a/do/mocks/KubernetesService.go +++ b/do/mocks/KubernetesService.go @@ -21,6 +21,7 @@ import ( type MockKubernetesService struct { ctrl *gomock.Controller recorder *MockKubernetesServiceMockRecorder + isgomock struct{} } // MockKubernetesServiceMockRecorder is the mock recorder for MockKubernetesService. diff --git a/do/mocks/Listen.go b/do/mocks/Listen.go index 49e600c1c..94882a4ea 100644 --- a/do/mocks/Listen.go +++ b/do/mocks/Listen.go @@ -19,6 +19,7 @@ import ( type MockListenerService struct { ctrl *gomock.Controller recorder *MockListenerServiceMockRecorder + isgomock struct{} } // MockListenerServiceMockRecorder is the mock recorder for MockListenerService. diff --git a/do/mocks/LoadBalancersService.go b/do/mocks/LoadBalancersService.go index ac9644046..d58affbfe 100644 --- a/do/mocks/LoadBalancersService.go +++ b/do/mocks/LoadBalancersService.go @@ -21,6 +21,7 @@ import ( type MockLoadBalancersService struct { ctrl *gomock.Controller recorder *MockLoadBalancersServiceMockRecorder + isgomock struct{} } // MockLoadBalancersServiceMockRecorder is the mock recorder for MockLoadBalancersService. diff --git a/do/mocks/MonitoringService.go b/do/mocks/MonitoringService.go index 42d33f7e4..a2c29be3c 100644 --- a/do/mocks/MonitoringService.go +++ b/do/mocks/MonitoringService.go @@ -21,6 +21,7 @@ import ( type MockMonitoringService struct { ctrl *gomock.Controller recorder *MockMonitoringServiceMockRecorder + isgomock struct{} } // MockMonitoringServiceMockRecorder is the mock recorder for MockMonitoringService. diff --git a/do/mocks/OAuthService.go b/do/mocks/OAuthService.go index eba9c703a..56c5c8179 100644 --- a/do/mocks/OAuthService.go +++ b/do/mocks/OAuthService.go @@ -20,6 +20,7 @@ import ( type MockOAuthService struct { ctrl *gomock.Controller recorder *MockOAuthServiceMockRecorder + isgomock struct{} } // MockOAuthServiceMockRecorder is the mock recorder for MockOAuthService. diff --git a/do/mocks/OneClickService.go b/do/mocks/OneClickService.go index 825b19ea6..7dd68384f 100644 --- a/do/mocks/OneClickService.go +++ b/do/mocks/OneClickService.go @@ -20,6 +20,7 @@ import ( type MockOneClickService struct { ctrl *gomock.Controller recorder *MockOneClickServiceMockRecorder + isgomock struct{} } // MockOneClickServiceMockRecorder is the mock recorder for MockOneClickService. diff --git a/do/mocks/ProjectsService.go b/do/mocks/ProjectsService.go index f50b07e76..28005dee5 100644 --- a/do/mocks/ProjectsService.go +++ b/do/mocks/ProjectsService.go @@ -21,6 +21,7 @@ import ( type MockProjectsService struct { ctrl *gomock.Controller recorder *MockProjectsServiceMockRecorder + isgomock struct{} } // MockProjectsServiceMockRecorder is the mock recorder for MockProjectsService. diff --git a/do/mocks/RegionsService.go b/do/mocks/RegionsService.go index 8c6d2165b..28b1b41a8 100644 --- a/do/mocks/RegionsService.go +++ b/do/mocks/RegionsService.go @@ -20,6 +20,7 @@ import ( type MockRegionsService struct { ctrl *gomock.Controller recorder *MockRegionsServiceMockRecorder + isgomock struct{} } // MockRegionsServiceMockRecorder is the mock recorder for MockRegionsService. diff --git a/do/mocks/RegistryService.go b/do/mocks/RegistryService.go index 74d41b9b4..ddb9165d5 100644 --- a/do/mocks/RegistryService.go +++ b/do/mocks/RegistryService.go @@ -21,6 +21,7 @@ import ( type MockRegistryService struct { ctrl *gomock.Controller recorder *MockRegistryServiceMockRecorder + isgomock struct{} } // MockRegistryServiceMockRecorder is the mock recorder for MockRegistryService. diff --git a/do/mocks/ReservedIPActionsService.go b/do/mocks/ReservedIPActionsService.go index 5725b1ca0..0b835976d 100644 --- a/do/mocks/ReservedIPActionsService.go +++ b/do/mocks/ReservedIPActionsService.go @@ -21,6 +21,7 @@ import ( type MockReservedIPActionsService struct { ctrl *gomock.Controller recorder *MockReservedIPActionsServiceMockRecorder + isgomock struct{} } // MockReservedIPActionsServiceMockRecorder is the mock recorder for MockReservedIPActionsService. diff --git a/do/mocks/ReservedIPsService.go b/do/mocks/ReservedIPsService.go index 1a16d115c..fb828b94f 100644 --- a/do/mocks/ReservedIPsService.go +++ b/do/mocks/ReservedIPsService.go @@ -21,6 +21,7 @@ import ( type MockReservedIPsService struct { ctrl *gomock.Controller recorder *MockReservedIPsServiceMockRecorder + isgomock struct{} } // MockReservedIPsServiceMockRecorder is the mock recorder for MockReservedIPsService. diff --git a/do/mocks/Runner.go b/do/mocks/Runner.go index 55a32a8e1..8bfcb48f4 100644 --- a/do/mocks/Runner.go +++ b/do/mocks/Runner.go @@ -19,6 +19,7 @@ import ( type MockRunner struct { ctrl *gomock.Controller recorder *MockRunnerMockRecorder + isgomock struct{} } // MockRunnerMockRecorder is the mock recorder for MockRunner. diff --git a/do/mocks/ServerlessService.go b/do/mocks/ServerlessService.go index 9a14a899b..f26c5c7ad 100644 --- a/do/mocks/ServerlessService.go +++ b/do/mocks/ServerlessService.go @@ -23,6 +23,7 @@ import ( type MockServerlessService struct { ctrl *gomock.Controller recorder *MockServerlessServiceMockRecorder + isgomock struct{} } // MockServerlessServiceMockRecorder is the mock recorder for MockServerlessService. diff --git a/do/mocks/SizesService.go b/do/mocks/SizesService.go index c9ffe8057..a2c57b032 100644 --- a/do/mocks/SizesService.go +++ b/do/mocks/SizesService.go @@ -20,6 +20,7 @@ import ( type MockSizesService struct { ctrl *gomock.Controller recorder *MockSizesServiceMockRecorder + isgomock struct{} } // MockSizesServiceMockRecorder is the mock recorder for MockSizesService. diff --git a/do/mocks/SnapshotsService.go b/do/mocks/SnapshotsService.go index 09086ae82..cb69ec7ac 100644 --- a/do/mocks/SnapshotsService.go +++ b/do/mocks/SnapshotsService.go @@ -20,6 +20,7 @@ import ( type MockSnapshotsService struct { ctrl *gomock.Controller recorder *MockSnapshotsServiceMockRecorder + isgomock struct{} } // MockSnapshotsServiceMockRecorder is the mock recorder for MockSnapshotsService. diff --git a/do/mocks/TagsService.go b/do/mocks/TagsService.go index 5a6ed17a8..5f31ce663 100644 --- a/do/mocks/TagsService.go +++ b/do/mocks/TagsService.go @@ -21,6 +21,7 @@ import ( type MockTagsService struct { ctrl *gomock.Controller recorder *MockTagsServiceMockRecorder + isgomock struct{} } // MockTagsServiceMockRecorder is the mock recorder for MockTagsService. diff --git a/do/mocks/UptimeChecksService.go b/do/mocks/UptimeChecksService.go index 926c34e4d..b4baf99b7 100644 --- a/do/mocks/UptimeChecksService.go +++ b/do/mocks/UptimeChecksService.go @@ -21,6 +21,7 @@ import ( type MockUptimeChecksService struct { ctrl *gomock.Controller recorder *MockUptimeChecksServiceMockRecorder + isgomock struct{} } // MockUptimeChecksServiceMockRecorder is the mock recorder for MockUptimeChecksService. diff --git a/do/mocks/VPCsService.go b/do/mocks/VPCsService.go index 33d86691f..a4f4873f7 100644 --- a/do/mocks/VPCsService.go +++ b/do/mocks/VPCsService.go @@ -21,6 +21,7 @@ import ( type MockVPCsService struct { ctrl *gomock.Controller recorder *MockVPCsServiceMockRecorder + isgomock struct{} } // MockVPCsServiceMockRecorder is the mock recorder for MockVPCsService. diff --git a/do/mocks/VolumeActionsService.go b/do/mocks/VolumeActionsService.go index 60a22b67f..423dc5d88 100644 --- a/do/mocks/VolumeActionsService.go +++ b/do/mocks/VolumeActionsService.go @@ -20,6 +20,7 @@ import ( type MockVolumeActionsService struct { ctrl *gomock.Controller recorder *MockVolumeActionsServiceMockRecorder + isgomock struct{} } // MockVolumeActionsServiceMockRecorder is the mock recorder for MockVolumeActionsService. diff --git a/do/mocks/VolumesService.go b/do/mocks/VolumesService.go index 48920d665..bad84e71c 100644 --- a/do/mocks/VolumesService.go +++ b/do/mocks/VolumesService.go @@ -21,6 +21,7 @@ import ( type MockVolumesService struct { ctrl *gomock.Controller recorder *MockVolumesServiceMockRecorder + isgomock struct{} } // MockVolumesServiceMockRecorder is the mock recorder for MockVolumesService. diff --git a/scripts/regenmocks.sh b/scripts/regenmocks.sh index 1e53bd73c..93599c946 100755 --- a/scripts/regenmocks.sh +++ b/scripts/regenmocks.sh @@ -18,6 +18,7 @@ mockgen -source certificates.go -package=mocks CertificateSservice > mocks/Certi mockgen -source databases.go -package=mocks DatabasesService > mocks/DatabasesService.go mockgen -source domains.go -package=mocks DomainService > mocks/DomainService.go mockgen -source droplet_actions.go -package=mocks DropletActionsService > mocks/DropletActionService.go +mockgen -source droplet_autoscale.go -package=mocks DropletAutoscaleService > mocks/DropletAutoscaleService.go mockgen -source droplets.go -package=mocks DropletsService > mocks/DropletsService.go mockgen -source firewalls.go -package=mocks FirewallsService > mocks/FirewallsService.go mockgen -source image_actions.go -package=mocks ImageActionsService > mocks/ImageActionsService.go