From e0f1c4b57f84780da3667aff837216c5ff080e41 Mon Sep 17 00:00:00 2001 From: Simon Emms Date: Fri, 16 Jun 2023 20:37:33 +0000 Subject: [PATCH] feat(pkg): add stop command --- cmd/stop.go | 37 +++++++++++++++++++++++++++++++++++++ pkg/hetzner/errors.go | 3 +++ pkg/hetzner/hetzner.go | 29 ++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/cmd/stop.go b/cmd/stop.go index 0aadb60..7b080a6 100644 --- a/cmd/stop.go +++ b/cmd/stop.go @@ -16,6 +16,13 @@ limitations under the License. package cmd import ( + "context" + "time" + + "github.com/loft-sh/devpod/pkg/client" + "github.com/loft-sh/devpod/pkg/log" + "github.com/mrsimonemms/devpod-provider-hetzner/pkg/hetzner" + "github.com/mrsimonemms/devpod-provider-hetzner/pkg/options" "github.com/spf13/cobra" ) @@ -23,6 +30,36 @@ import ( var stopCmd = &cobra.Command{ Use: "stop", Short: "Stop an instance", + RunE: func(_ *cobra.Command, args []string) error { + options, err := options.FromEnv(false) + if err != nil { + return err + } + + ctx := context.Background() + + hetznerClient := hetzner.NewHetzner(options.Token) + + err = hetznerClient.Stop(ctx, options.MachineID) + if err != nil { + return err + } + + // Wait until it's stopped + for { + status, err := hetznerClient.Status(ctx, options.MachineID) + if err != nil { + log.Default.Errorf("Error retrieving server status: %v", err) + break + } else if status == client.StatusStopped { + break + } + + time.Sleep(time.Second) + } + + return nil + }, } func init() { diff --git a/pkg/hetzner/errors.go b/pkg/hetzner/errors.go index 0f18836..73b469f 100644 --- a/pkg/hetzner/errors.go +++ b/pkg/hetzner/errors.go @@ -6,6 +6,9 @@ import ( ) var ( + ErrMultipleServersFound = func(name string) error { + return fmt.Errorf("multiple server with name %s found", name) + } ErrMultipleVolumesFound = func(name string) error { return fmt.Errorf("multiple volumes with name %s found", name) } diff --git a/pkg/hetzner/hetzner.go b/pkg/hetzner/hetzner.go index dcec83f..a77df6e 100644 --- a/pkg/hetzner/hetzner.go +++ b/pkg/hetzner/hetzner.go @@ -124,8 +124,21 @@ func (h *Hetzner) Delete(ctx context.Context, name string) error { return nil } -func (h *Hetzner) GetByName(ctx context.Context, name string) (interface{}, error) { - return nil, nil +func (h *Hetzner) GetByName(ctx context.Context, name string) (*hcloud.Server, error) { + servers, _, err := h.client.Server.List(ctx, hcloud.ServerListOpts{Name: name}) + if err != nil { + return nil, err + } + + serverLength := len(servers) + if serverLength > 1 { + return nil, ErrMultipleServersFound(name) + } + if serverLength == 0 { + return nil, nil + } + + return servers[0], nil } func (h *Hetzner) Init(ctx context.Context) error { @@ -164,7 +177,17 @@ func (h *Hetzner) Status(ctx context.Context, name string) (client.Status, error } func (h *Hetzner) Stop(ctx context.Context, name string) error { - return nil + server, err := h.GetByName(ctx, name) + if err != nil { + return err + } + if server == nil { + return nil + } + + _, _, err = h.client.Server.DeleteWithResult(ctx, server) + + return err } func (h *Hetzner) volumeByName(ctx context.Context, name string) (*hcloud.Volume, error) {