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..89c80d88f 100644 --- a/builder/hcloud/step_create_server.go +++ b/builder/hcloud/step_create_server.go @@ -67,21 +67,31 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu // Store the server id for later state.Put("server_id", serverCreateResult.Server.ID) - _, errCh := client.Action.WatchProgress(context.TODO(), serverCreateResult.Action) - for { - select { - case err1 := <-errCh: - if err1 == nil { - return multistep.ActionContinue - } else { - err := fmt.Errorf("Error creating server: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - + if err := waitForAction(context.TODO(), client, serverCreateResult.Action); err != nil { + err := fmt.Errorf("Error creating server: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + for _, nextAction := range serverCreateResult.NextActions { + if err := waitForAction(context.TODO(), client, nextAction); err != nil { + err := fmt.Errorf("Error creating server: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } } + + if c.RescueMode != "" { + if err := setRescue(context.TODO(), 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 +111,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 := waitForAction(ctx, client, action); 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 := waitForAction(ctx, client, res.Action); err != nil { + return err + } + } + if rescueChanged { + action, _, err := client.Server.Reset(ctx, server) + if err != nil { + return err + } + if err := waitForAction(ctx, client, action); err != nil { + return err + } + } + return nil +} + +func waitForAction(ctx context.Context, client *hcloud.Client, action *hcloud.Action) error { + _, errCh := client.Action.WatchProgress(ctx, action) + if err := <-errCh; err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/LICENSE b/vendor/github.com/hetznercloud/hcloud-go/LICENSE old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go old mode 100644 new mode 100755 index c31af0ca4..a261891e2 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/action.go @@ -74,7 +74,7 @@ type ActionClient struct { client *Client } -// GetByID retrieves an action by its ID. +// GetByID retrieves an action by its ID. If the action does not exist, nil is returned. func (c *ActionClient) GetByID(ctx context.Context, id int) (*Action, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/actions/%d", id), nil) if err != nil { diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/client.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/client.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go old mode 100644 new mode 100755 index 7b4429feb..b0717f942 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/datacenter.go @@ -29,7 +29,7 @@ type DatacenterClient struct { client *Client } -// GetByID retrieves a datacenter by its ID. +// GetByID retrieves a datacenter by its ID. If the datacenter does not exist, nil is returned. func (c *DatacenterClient) GetByID(ctx context.Context, id int) (*Datacenter, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/datacenters/%d", id), nil) if err != nil { @@ -47,7 +47,7 @@ func (c *DatacenterClient) GetByID(ctx context.Context, id int) (*Datacenter, *R return DatacenterFromSchema(body.Datacenter), resp, nil } -// GetByName retrieves an datacenter by its name. +// GetByName retrieves an datacenter by its name. If the datacenter does not exist, nil is returned. func (c *DatacenterClient) GetByName(ctx context.Context, name string) (*Datacenter, *Response, error) { path := "/datacenters?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -67,7 +67,8 @@ func (c *DatacenterClient) GetByName(ctx context.Context, name string) (*Datacen return DatacenterFromSchema(body.Datacenters[0]), resp, nil } -// Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it retrieves a datacenter by its name. +// Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it +// retrieves a datacenter by its name. If the datacenter does not exist, nil is returned. func (c *DatacenterClient) Get(ctx context.Context, idOrName string) (*Datacenter, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/error.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/error.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go old mode 100644 new mode 100755 index e1372db06..7fe2c55d0 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/floating_ip.go @@ -50,7 +50,8 @@ type FloatingIPClient struct { client *Client } -// GetByID retrieves a Floating IP by its ID. +// GetByID retrieves a Floating IP by its ID. If the Floating IP does not exist, +// nil is returned. func (c *FloatingIPClient) GetByID(ctx context.Context, id int) (*FloatingIP, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/floating_ips/%d", id), nil) if err != nil { diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go old mode 100644 new mode 100755 index 8d3b398a3..032342ef4 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/hcloud.go @@ -2,4 +2,4 @@ package hcloud // Version is the library's version following Semantic Versioning. -const Version = "1.9.0" +const Version = "1.11.0" diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/helper.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/helper.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go old mode 100644 new mode 100755 index 7089facd3..4ebe4c3f5 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/image.go @@ -71,7 +71,7 @@ type ImageClient struct { client *Client } -// GetByID retrieves an image by its ID. +// GetByID retrieves an image by its ID. If the image does not exist, nil is returned. func (c *ImageClient) GetByID(ctx context.Context, id int) (*Image, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/images/%d", id), nil) if err != nil { @@ -89,7 +89,7 @@ func (c *ImageClient) GetByID(ctx context.Context, id int) (*Image, *Response, e return ImageFromSchema(body.Image), resp, nil } -// GetByName retrieves an image by its name. +// GetByName retrieves an image by its name. If the image does not exist, nil is returned. func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Response, error) { path := "/images?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -109,7 +109,8 @@ func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Resp return ImageFromSchema(body.Images[0]), resp, nil } -// Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it retrieves an image by its name. +// Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it +// retrieves an image by its name. If the image does not exist, nil is returned. func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/iso.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/iso.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go old mode 100644 new mode 100755 index 4ab55ef11..5269b7e76 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/location.go @@ -25,7 +25,7 @@ type LocationClient struct { client *Client } -// GetByID retrieves a location by its ID. +// GetByID retrieves a location by its ID. If the location does not exist, nil is returned. func (c *LocationClient) GetByID(ctx context.Context, id int) (*Location, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/locations/%d", id), nil) if err != nil { @@ -43,7 +43,7 @@ func (c *LocationClient) GetByID(ctx context.Context, id int) (*Location, *Respo return LocationFromSchema(body.Location), resp, nil } -// GetByName retrieves an location by its name. +// GetByName retrieves an location by its name. If the location does not exist, nil is returned. func (c *LocationClient) GetByName(ctx context.Context, name string) (*Location, *Response, error) { path := "/locations?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -63,7 +63,8 @@ func (c *LocationClient) GetByName(ctx context.Context, name string) (*Location, return LocationFromSchema(body.Locations[0]), resp, nil } -// Get retrieves a location by its ID if the input can be parsed as an integer, otherwise it retrieves a location by its name. +// Get retrieves a location by its ID if the input can be parsed as an integer, otherwise it +// retrieves a location by its name. If the location does not exist, nil is returned. func (c *LocationClient) Get(ctx context.Context, idOrName string) (*Location, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/pricing.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/pricing.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go old mode 100644 new mode 100755 index 828033c4d..47a194f3a --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema.go @@ -35,6 +35,15 @@ func ActionFromSchema(s schema.Action) *Action { return action } +// ActionsFromSchema converts a slice of schema.Action to a slice of Action. +func ActionsFromSchema(s []schema.Action) []*Action { + var actions []*Action + for _, a := range s { + actions = append(actions, ActionFromSchema(a)) + } + return actions +} + // FloatingIPFromSchema converts a schema.FloatingIP to a FloatingIP. func FloatingIPFromSchema(s schema.FloatingIP) *FloatingIP { f := &FloatingIP{ diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/action.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/action.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/datacenter.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/datacenter.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/error.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/error.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/floating_ip.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/floating_ip.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/image.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/image.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/iso.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/iso.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/location.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/location.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/meta.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/meta.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/pricing.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/pricing.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go old mode 100644 new mode 100755 index f58e3b8ff..edaf54ce2 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server.go @@ -90,9 +90,10 @@ type ServerCreateRequest struct { // ServerCreateResponse defines the schema of the response when // creating a server. type ServerCreateResponse struct { - Server Server `json:"server"` - Action Action `json:"action"` - RootPassword *string `json:"root_password"` + Server Server `json:"server"` + Action Action `json:"action"` + RootPassword *string `json:"root_password"` + NextActions []Action `json:"next_actions"` } // ServerUpdateRequest defines the schema of the request to update a server. diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server_type.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/server_type.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/ssh_key.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/ssh_key.go old mode 100644 new mode 100755 diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/volume.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/volume.go old mode 100644 new mode 100755 index aa6c699e9..a8aa79341 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/volume.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/schema/volume.go @@ -28,8 +28,9 @@ type VolumeCreateRequest struct { // VolumeCreateResponse defines the schema of the response // when creating a volume. type VolumeCreateResponse struct { - Volume Volume `json:"volume"` - Action *Action `json:"action"` + Volume Volume `json:"volume"` + Action *Action `json:"action"` + NextActions []Action `json:"next_actions"` } // VolumeListResponse defines the schema of the response diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go old mode 100644 new mode 100755 index b85861fc3..ad0b16e9d --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/server.go @@ -97,7 +97,7 @@ type ServerClient struct { client *Client } -// GetByID retrieves a server by its ID. +// GetByID retrieves a server by its ID. If the server does not exist, nil is returned. func (c *ServerClient) GetByID(ctx context.Context, id int) (*Server, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/servers/%d", id), nil) if err != nil { @@ -115,7 +115,7 @@ func (c *ServerClient) GetByID(ctx context.Context, id int) (*Server, *Response, return ServerFromSchema(body.Server), resp, nil } -// GetByName retreives a server by its name. +// GetByName retreives a server by its name. If the server does not exist, nil is returned. func (c *ServerClient) GetByName(ctx context.Context, name string) (*Server, *Response, error) { path := "/servers?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -135,7 +135,8 @@ func (c *ServerClient) GetByName(ctx context.Context, name string) (*Server, *Re return ServerFromSchema(body.Servers[0]), resp, nil } -// Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it retrieves a server by its name. +// Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it +// retrieves a server by its name. If the server does not exist, nil is returned. func (c *ServerClient) Get(ctx context.Context, idOrName string) (*Server, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) @@ -228,6 +229,7 @@ type ServerCreateResult struct { Server *Server Action *Action RootPassword string + NextActions []*Action } // Create creates a new server. @@ -286,8 +288,9 @@ func (c *ServerClient) Create(ctx context.Context, opts ServerCreateOpts) (Serve return ServerCreateResult{}, resp, err } result := ServerCreateResult{ - Server: ServerFromSchema(respBody.Server), - Action: ActionFromSchema(respBody.Action), + Server: ServerFromSchema(respBody.Server), + Action: ActionFromSchema(respBody.Action), + NextActions: ActionsFromSchema(respBody.NextActions), } if respBody.RootPassword != nil { result.RootPassword = *respBody.RootPassword diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go old mode 100644 new mode 100755 index 8f4166c17..6f12bd680 --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/server_type.go @@ -49,7 +49,7 @@ type ServerTypeClient struct { client *Client } -// GetByID retrieves a server type by its ID. +// GetByID retrieves a server type by its ID. If the server type does not exist, nil is returned. func (c *ServerTypeClient) GetByID(ctx context.Context, id int) (*ServerType, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/server_types/%d", id), nil) if err != nil { @@ -67,7 +67,7 @@ func (c *ServerTypeClient) GetByID(ctx context.Context, id int) (*ServerType, *R return ServerTypeFromSchema(body.ServerType), resp, nil } -// GetByName retrieves a server type by its name. +// GetByName retrieves a server type by its name. If the server type does not exist, nil is returned. func (c *ServerTypeClient) GetByName(ctx context.Context, name string) (*ServerType, *Response, error) { path := "/server_types?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -87,7 +87,8 @@ func (c *ServerTypeClient) GetByName(ctx context.Context, name string) (*ServerT return ServerTypeFromSchema(body.ServerTypes[0]), resp, nil } -// Get retrieves a server type by its ID if the input can be parsed as an integer, otherwise it retrieves a server type by its name. +// Get retrieves a server type by its ID if the input can be parsed as an integer, otherwise it +// retrieves a server type by its name. If the server type does not exist, nil is returned. func (c *ServerTypeClient) Get(ctx context.Context, idOrName string) (*ServerType, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go old mode 100644 new mode 100755 index 2ab55bff6..7db8f0a9e --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/ssh_key.go @@ -26,7 +26,7 @@ type SSHKeyClient struct { client *Client } -// GetByID retrieves a SSH key by its ID. +// GetByID retrieves a SSH key by its ID. If the SSH key does not exist, nil is returned. func (c *SSHKeyClient) GetByID(ctx context.Context, id int) (*SSHKey, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/ssh_keys/%d", id), nil) if err != nil { @@ -44,7 +44,7 @@ func (c *SSHKeyClient) GetByID(ctx context.Context, id int) (*SSHKey, *Response, return SSHKeyFromSchema(body.SSHKey), resp, nil } -// GetByName retrieves a SSH key by its name. +// GetByName retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. func (c *SSHKeyClient) GetByName(ctx context.Context, name string) (*SSHKey, *Response, error) { path := "/ssh_keys?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -64,7 +64,7 @@ func (c *SSHKeyClient) GetByName(ctx context.Context, name string) (*SSHKey, *Re return SSHKeyFromSchema(body.SSHKeys[0]), resp, nil } -// GetByFingerprint retreives a SSH key by its fingerprint. +// GetByFingerprint retreives a SSH key by its fingerprint. If the SSH key does not exist, nil is returned. func (c *SSHKeyClient) GetByFingerprint(ctx context.Context, fingerprint string) (*SSHKey, *Response, error) { path := "/ssh_keys?fingerprint=" + url.QueryEscape(fingerprint) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -84,7 +84,8 @@ func (c *SSHKeyClient) GetByFingerprint(ctx context.Context, fingerprint string) return SSHKeyFromSchema(body.SSHKeys[0]), resp, nil } -// Get retrieves a SSH key by its ID if the input can be parsed as an integer, otherwise it retrieves a SSH key by its name. +// Get retrieves a SSH key by its ID if the input can be parsed as an integer, otherwise it +// retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. func (c *SSHKeyClient) Get(ctx context.Context, idOrName string) (*SSHKey, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) diff --git a/vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go b/vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go old mode 100644 new mode 100755 index 4e5f4d0a9..735f3918b --- a/vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go +++ b/vendor/github.com/hetznercloud/hcloud-go/hcloud/volume.go @@ -36,7 +36,7 @@ type VolumeClient struct { client *Client } -// GetByID retrieves a volume by its ID. +// GetByID retrieves a volume by its ID. If the volume does not exist, nil is returned. func (c *VolumeClient) GetByID(ctx context.Context, id int) (*Volume, *Response, error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/volumes/%d", id), nil) if err != nil { @@ -54,7 +54,7 @@ func (c *VolumeClient) GetByID(ctx context.Context, id int) (*Volume, *Response, return VolumeFromSchema(body.Volume), resp, nil } -// GetByName retrieves a volume by its name. +// GetByName retrieves a volume by its name. If the volume does not exist, nil is returned. func (c *VolumeClient) GetByName(ctx context.Context, name string) (*Volume, *Response, error) { path := "/volumes?name=" + url.QueryEscape(name) req, err := c.client.NewRequest(ctx, "GET", path, nil) @@ -74,8 +74,8 @@ func (c *VolumeClient) GetByName(ctx context.Context, name string) (*Volume, *Re return VolumeFromSchema(body.Volumes[0]), resp, nil } -// Get retrieves a volume by its ID if the input can be parsed as an integer, -// otherwise it retrieves a volume by its name. +// Get retrieves a volume by its ID if the input can be parsed as an integer, otherwise it +// retrieves a volume by its name. If the volume does not exist, nil is returned. func (c *VolumeClient) Get(ctx context.Context, idOrName string) (*Volume, *Response, error) { if id, err := strconv.Atoi(idOrName); err == nil { return c.GetByID(ctx, int(id)) @@ -161,8 +161,9 @@ func (o VolumeCreateOpts) Validate() error { // VolumeCreateResult is the result of creating a volume. type VolumeCreateResult struct { - Volume *Volume - Action *Action + Volume *Volume + Action *Action + NextActions []*Action } // Create creates a new volume with the given options. @@ -209,8 +210,9 @@ func (c *VolumeClient) Create(ctx context.Context, opts VolumeCreateOpts) (Volum } return VolumeCreateResult{ - Volume: VolumeFromSchema(respBody.Volume), - Action: action, + Volume: VolumeFromSchema(respBody.Volume), + Action: action, + NextActions: ActionsFromSchema(respBody.NextActions), }, resp, 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