Repository: hetznercloud/hcloud-go
Pull request #12 (2017-12-07 14:54:07)

Implement some server actions


Patch:
diff --git a/hcloud/schema/server.go b/hcloud/schema/server.go
index 53f6561..5fc90a6 100644
--- a/hcloud/schema/server.go
+++ b/hcloud/schema/server.go
@@ -75,3 +75,64 @@ type ServerCreateResponse struct {
 	Server Server `json:"server"`
 	Action Action `json:"action"`
 }
+
+// ServerActionPoweronRequest defines the schema for the request to
+// create a poweron server action.
+type ServerActionPoweronRequest struct{}
+
+// ServerActionPoweronResponse defines the schema of the response when
+// creating a poweron server action.
+type ServerActionPoweronResponse struct {
+	Action Action `json:"action"`
+}
+
+// ServerActionPoweroffRequest defines the schema for the request to
+// create a poweroff server action.
+type ServerActionPoweroffRequest struct{}
+
+// ServerActionPoweroffResponse defines the schema of the response when
+// creating a poweroff server action.
+type ServerActionPoweroffResponse struct {
+	Action Action `json:"action"`
+}
+
+// ServerActionRebootRequest defines the schema for the request to
+// create a reboot server action.
+type ServerActionRebootRequest struct{}
+
+// ServerActionRebootResponse defines the schema of the response when
+// creating a reboot server action.
+type ServerActionRebootResponse struct {
+	Action Action `json:"action"`
+}
+
+// ServerActionResetRequest defines the schema for the request to
+// create a reset server action.
+type ServerActionResetRequest struct{}
+
+// ServerActionResetResponse defines the schema of the response when
+// creating a reset server action.
+type ServerActionResetResponse struct {
+	Action Action `json:"action"`
+}
+
+// ServerActionShutdownRequest defines the schema for the request to
+// create a shutdown server action.
+type ServerActionShutdownRequest struct{}
+
+// ServerActionShutdownResponse defines the schema of the response when
+// creating a shutdown server action.
+type ServerActionShutdownResponse struct {
+	Action Action `json:"action"`
+}
+
+// ServerActionResetPasswordRequest defines the schema for the request to
+// create a reset_password server action.
+type ServerActionResetPasswordRequest struct{}
+
+// ServerActionResetPasswordResponse defines the schema of the response when
+// creating a reset_password server action.
+type ServerActionResetPasswordResponse struct {
+	Action       Action `json:"action"`
+	RootPassword string `json:"root_password"`
+}
diff --git a/hcloud/server.go b/hcloud/server.go
index 3c7f255..689dc09 100644
--- a/hcloud/server.go
+++ b/hcloud/server.go
@@ -275,3 +275,108 @@ func (c *ServerClient) Delete(ctx context.Context, id int) (*Response, error) {
 	}
 	return c.client.Do(req, nil)
 }
+
+// Poweron starts a server.
+func (c *ServerClient) Poweron(ctx context.Context, server *Server) (*Action, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/poweron", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.ServerActionPoweronResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
+
+// Reboot reboots a server.
+func (c *ServerClient) Reboot(ctx context.Context, server *Server) (*Action, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/reboot", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.ServerActionRebootResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
+
+// Reset resets a server.
+func (c *ServerClient) Reset(ctx context.Context, server *Server) (*Action, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/reset", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.ServerActionResetResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
+
+// Shutdown shuts down a server.
+func (c *ServerClient) Shutdown(ctx context.Context, server *Server) (*Action, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/shutdown", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.ServerActionShutdownResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
+
+// Poweroff stops a server.
+func (c *ServerClient) Poweroff(ctx context.Context, server *Server) (*Action, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/poweroff", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.ServerActionPoweroffResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
+
+// ServerResetPasswordResult is the result of resetting a server's password.
+type ServerResetPasswordResult struct {
+	Action       *Action
+	RootPassword string
+}
+
+// ResetPassword resets a server's password.
+func (c *ServerClient) ResetPassword(ctx context.Context, server *Server) (ServerResetPasswordResult, *Response, error) {
+	path := fmt.Sprintf("/servers/%d/actions/reset_password", server.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, nil)
+	if err != nil {
+		return ServerResetPasswordResult{}, nil, err
+	}
+
+	respBody := schema.ServerActionResetPasswordResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return ServerResetPasswordResult{}, resp, err
+	}
+	return ServerResetPasswordResult{
+		Action:       ActionFromSchema(respBody.Action),
+		RootPassword: respBody.RootPassword,
+	}, resp, nil
+}


Test patch:
diff --git a/hcloud/server_test.go b/hcloud/server_test.go
index ea4f820..4559573 100644
--- a/hcloud/server_test.go
+++ b/hcloud/server_test.go
@@ -412,3 +412,139 @@ func TestServersDelete(t *testing.T) {
 		t.Fatalf("Server.Delete failed: %s", err)
 	}
 }
+
+func TestServerClientPoweron(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/poweron", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionPoweronResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+		})
+	})
+
+	ctx := context.Background()
+	action, _, err := env.Client.Server.Poweron(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", action.ID)
+	}
+}
+
+func TestServerClientReboot(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/reboot", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionRebootResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+		})
+	})
+
+	ctx := context.Background()
+	action, _, err := env.Client.Server.Reboot(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", action.ID)
+	}
+}
+
+func TestServerClientReset(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/reset", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionResetResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+		})
+	})
+
+	ctx := context.Background()
+	action, _, err := env.Client.Server.Reset(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", action.ID)
+	}
+}
+
+func TestServerClientShutdown(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/shutdown", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionShutdownResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+		})
+	})
+
+	ctx := context.Background()
+	action, _, err := env.Client.Server.Shutdown(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", action.ID)
+	}
+}
+
+func TestServerClientPoweroff(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/poweroff", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionPoweroffResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+		})
+	})
+
+	ctx := context.Background()
+	action, _, err := env.Client.Server.Poweroff(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", action.ID)
+	}
+}
+
+func TestServerClientResetPassword(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1/actions/reset_password", func(w http.ResponseWriter, r *http.Request) {
+		json.NewEncoder(w).Encode(schema.ServerActionResetPasswordResponse{
+			Action: schema.Action{
+				ID: 1,
+			},
+			RootPassword: "secret",
+		})
+	})
+
+	ctx := context.Background()
+	result, _, err := env.Client.Server.ResetPassword(ctx, &Server{ID: 1})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if result.Action.ID != 1 {
+		t.Errorf("unexpected action ID: %d", result.Action.ID)
+	}
+	if result.RootPassword != "secret" {
+		t.Errorf("unexpected root password: %v", result.RootPassword)
+	}
+}