Repository: hetznercloud/hcloud-go
Pull request #143 (2020-07-21 07:10:58)

Add `ChangeType` to `LoadBalancer`


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index dd1ccc4..c525a60 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,7 @@
 * Fix nil pointer dereference when creating a Load Balancer with HTTP(S)
   service and not providing HTTP-specific options
 * Add `IncludedTraffic`, `OutgoingTraffic` and `IngoingTraffic` fields to `LoadBalancer`
+* Add `ChangeType()` method to the Load Balancer client
 
 ## v1.18.2
 
diff --git a/hcloud/load_balancer.go b/hcloud/load_balancer.go
index a929509..3ba1d39 100644
--- a/hcloud/load_balancer.go
+++ b/hcloud/load_balancer.go
@@ -806,3 +806,35 @@ func (c *LoadBalancerClient) DisablePublicInterface(ctx context.Context, loadBal
 	}
 	return ActionFromSchema(respBody.Action), resp, err
 }
+
+// LoadBalancerChangeTypeOpts specifies options for changing a Load Balancer's type.
+type LoadBalancerChangeTypeOpts struct {
+	LoadBalancerType *LoadBalancerType // new Load Balancer type
+}
+
+// ChangeType changes a Load Balancer's type.
+func (c *LoadBalancerClient) ChangeType(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeTypeOpts) (*Action, *Response, error) {
+	reqBody := schema.LoadBalancerActionChangeTypeRequest{}
+	if opts.LoadBalancerType.ID != 0 {
+		reqBody.LoadBalancerType = opts.LoadBalancerType.ID
+	} else {
+		reqBody.LoadBalancerType = opts.LoadBalancerType.Name
+	}
+	reqBodyData, err := json.Marshal(reqBody)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	path := fmt.Sprintf("/load_balancers/%d/actions/change_type", loadBalancer.ID)
+	req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
+	if err != nil {
+		return nil, nil, err
+	}
+
+	respBody := schema.LoadBalancerActionChangeTypeResponse{}
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return nil, resp, err
+	}
+	return ActionFromSchema(respBody.Action), resp, nil
+}
diff --git a/hcloud/schema/load_balancer.go b/hcloud/schema/load_balancer.go
index fe5b6b9..97653ab 100644
--- a/hcloud/schema/load_balancer.go
+++ b/hcloud/schema/load_balancer.go
@@ -335,3 +335,11 @@ type LoadBalancerActionDisablePublicInterfaceRequest struct{}
 type LoadBalancerActionDisablePublicInterfaceResponse struct {
 	Action Action `json:"action"`
 }
+
+type LoadBalancerActionChangeTypeRequest struct {
+	LoadBalancerType interface{} `json:"load_balancer_type"` // int or string
+}
+
+type LoadBalancerActionChangeTypeResponse struct {
+	Action Action `json:"action"`
+}


Test patch:
diff --git a/hcloud/load_balancer_test.go b/hcloud/load_balancer_test.go
index db2fcd6..ded879d 100644
--- a/hcloud/load_balancer_test.go
+++ b/hcloud/load_balancer_test.go
@@ -796,3 +796,72 @@ func TestLoadBalancerClientDisablePublicInterface(t *testing.T) {
 		t.Errorf("unexpected action ID: %d", action.ID)
 	}
 }
+
+func TestLoadBalancerClientChangeType(t *testing.T) {
+	var (
+		ctx          = context.Background()
+		loadBalancer = &LoadBalancer{ID: 1}
+	)
+
+	t.Run("with Load Balancer type ID", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/load_balancers/1/actions/change_type", func(w http.ResponseWriter, r *http.Request) {
+			var reqBody schema.LoadBalancerActionChangeTypeRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if id, ok := reqBody.LoadBalancerType.(float64); !ok || id != 1 {
+				t.Errorf("unexpected Load Balancer type ID: %v", reqBody.LoadBalancerType)
+			}
+			json.NewEncoder(w).Encode(schema.LoadBalancerActionChangeTypeResponse{
+				Action: schema.Action{
+					ID: 1,
+				},
+			})
+		})
+
+		opts := LoadBalancerChangeTypeOpts{
+			LoadBalancerType: &LoadBalancerType{ID: 1},
+		}
+		action, _, err := env.Client.LoadBalancer.ChangeType(ctx, loadBalancer, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if action.ID != 1 {
+			t.Errorf("unexpected action ID: %d", action.ID)
+		}
+	})
+
+	t.Run("with Load Balancer type name", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/load_balancers/1/actions/change_type", func(w http.ResponseWriter, r *http.Request) {
+			var reqBody schema.LoadBalancerActionChangeTypeRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if name, ok := reqBody.LoadBalancerType.(string); !ok || name != "type" {
+				t.Errorf("unexpected Load Balancer type name: %v", reqBody.LoadBalancerType)
+			}
+			json.NewEncoder(w).Encode(schema.LoadBalancerActionChangeTypeResponse{
+				Action: schema.Action{
+					ID: 1,
+				},
+			})
+		})
+
+		opts := LoadBalancerChangeTypeOpts{
+			LoadBalancerType: &LoadBalancerType{Name: "type"},
+		}
+		action, _, err := env.Client.LoadBalancer.ChangeType(ctx, loadBalancer, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if action.ID != 1 {
+			t.Errorf("unexpected action ID: %d", action.ID)
+		}
+	})
+}