From 064e6c7e0866cd1a90ac5c02f07574a430f8766d Mon Sep 17 00:00:00 2001 From: dedene Date: Fri, 23 Nov 2018 20:35:32 +0100 Subject: [PATCH] Add support for builds using rescue mode --- builder/hcloud/config.go | 2 + builder/hcloud/step_create_server.go | 59 ++++++++++++++++++- .../docs/builders/hetzner-cloud.html.md | 2 + 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/builder/hcloud/config.go b/builder/hcloud/config.go index 3de43ab04..368eda258 100644 --- a/builder/hcloud/config.go +++ b/builder/hcloud/config.go @@ -35,6 +35,8 @@ type Config struct { UserDataFile string `mapstructure:"user_data_file"` SSHKeys []string `mapstructure:"ssh_keys"` + RescueMode string `mapstructure:"rescue"` + ctx interpolate.Context } diff --git a/builder/hcloud/step_create_server.go b/builder/hcloud/step_create_server.go index eca8d54ae..96d86d38a 100644 --- a/builder/hcloud/step_create_server.go +++ b/builder/hcloud/step_create_server.go @@ -68,11 +68,12 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu state.Put("server_id", serverCreateResult.Server.ID) _, errCh := client.Action.WatchProgress(context.TODO(), serverCreateResult.Action) +watch: for { select { case err1 := <-errCh: if err1 == nil { - return multistep.ActionContinue + break watch } else { err := fmt.Errorf("Error creating server: %s", err) state.Put("error", err) @@ -82,6 +83,17 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu } } + + if c.RescueMode != "" { + if err := setRescue(ctx, client, serverCreateResult.Server, c.RescueMode, sshKeys); err != nil { + err := fmt.Errorf("Error enabling rescue mode: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } + + return multistep.ActionContinue } func (s *stepCreateServer) Cleanup(state multistep.StateBag) { @@ -101,3 +113,48 @@ func (s *stepCreateServer) Cleanup(state multistep.StateBag) { "Error destroying server. Please destroy it manually: %s", err)) } } + +func setRescue(ctx context.Context, client *hcloud.Client, server *hcloud.Server, rescue string, sshKeys []*hcloud.SSHKey) error { + rescueChanged := false + if server.RescueEnabled { + rescueChanged = true + action, _, err := client.Server.DisableRescue(ctx, server) + if err != nil { + return err + } + if err := waitForServerAction(ctx, client, action, server); err != nil { + return err + } + } + if rescue != "" { + rescueChanged = true + res, _, err := client.Server.EnableRescue(ctx, server, hcloud.ServerEnableRescueOpts{ + Type: hcloud.ServerRescueType(rescue), + SSHKeys: sshKeys, + }) + if err != nil { + return err + } + if err := waitForServerAction(ctx, client, res.Action, server); err != nil { + return err + } + } + if rescueChanged { + action, _, err := client.Server.Reset(ctx, server) + if err != nil { + return err + } + if err := waitForServerAction(ctx, client, action, server); err != nil { + return err + } + } + return nil +} + +func waitForServerAction(ctx context.Context, client *hcloud.Client, action *hcloud.Action, server *hcloud.Server) error { + _, errCh := client.Action.WatchProgress(ctx, action) + if err := <-errCh; err != nil { + return err + } + return nil +} diff --git a/website/source/docs/builders/hetzner-cloud.html.md b/website/source/docs/builders/hetzner-cloud.html.md index 4b0ab5f5e..d18f5e761 100644 --- a/website/source/docs/builders/hetzner-cloud.html.md +++ b/website/source/docs/builders/hetzner-cloud.html.md @@ -72,6 +72,8 @@ builder. - `ssh_keys` (array of strings) - List of SSH keys by name or id to be added to image on launch. +- `rescue` (string) - Enable and boot in to the specified rescue system. This enables simple installation of custom operating systems. `linux64` `linux32` or `freebsd64` + ## Basic Example Here is a basic example. It is completely valid as soon as you enter your own