Skip to content

Commit

Permalink
fix: error when updating IPv6 Primary IP
Browse files Browse the repository at this point in the history
The API returns a CIDR range in the `ip` field for ipv6 primary IPs. This
caused the `PrimaryIPClient.Update` call to fail, because the response
was parsed as a `net.IP`, but should have been parsed using `net.ParseNetwork`.

The required logic was already implemented in the `PrimaryIPFromSchema`
function, but not used for the update call.

With this commit, the struct `hcloud.PrimaryIPUpdateResult` is marked as
deprecated, because using it to parse the response causes the error.

This error was originally found in hcloud-cli, and caused following error
message:

    ➜  ~ hcloud primary-ip update --auto-delete=false test-ip
    hcloud: updating Primary IP test-ip failed: invalid IP address: 2001:db8::/64
  • Loading branch information
apricote committed Nov 10, 2022
1 parent 55dafa9 commit 7501b60
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 6 deletions.
6 changes: 4 additions & 2 deletions hcloud/primary_ip.go
Expand Up @@ -92,6 +92,8 @@ type PrimaryIPUpdateOpts struct {

// PrimaryIPUpdateResult defines the response
// when updating a Primary IP.
// This struct is deprecated because it does not work with IPv6.
// Please use github.com/hetznercloud/hcloud-go/hcloud/schema.PrimaryIPUpdateResult instead.
type PrimaryIPUpdateResult struct {
PrimaryIP PrimaryIP `json:"primary_ip"`
}
Expand Down Expand Up @@ -311,12 +313,12 @@ func (c *PrimaryIPClient) Update(ctx context.Context, primaryIP *PrimaryIP, reqB
return nil, nil, err
}

respBody := PrimaryIPUpdateResult{}
var respBody schema.PrimaryIPUpdateResult
resp, err := c.client.Do(req, &respBody)
if err != nil {
return nil, resp, err
}
return &respBody.PrimaryIP, resp, nil
return PrimaryIPFromSchema(respBody.PrimaryIP), resp, nil
}

// Assign a Primary IP to a resource
Expand Down
12 changes: 8 additions & 4 deletions hcloud/primary_ip_test.go
Expand Up @@ -3,6 +3,7 @@ package hcloud
import (
"context"
"encoding/json"
"net"
"net/http"
"testing"

Expand Down Expand Up @@ -333,8 +334,8 @@ func TestPrimaryIPClient(t *testing.T) {
t.Log(cmp.Diff(expectedReqBody, reqBody))
t.Error("unexpected request body")
}
json.NewEncoder(w).Encode(PrimaryIPUpdateResult{
PrimaryIP: PrimaryIP{ID: 1},
json.NewEncoder(w).Encode(schema.PrimaryIPUpdateResult{
PrimaryIP: schema.PrimaryIP{ID: 1, IP: "2001:db8::/64"},
})
})

Expand All @@ -347,11 +348,14 @@ func TestPrimaryIPClient(t *testing.T) {
Labels: &labels,
}

primaryIP := PrimaryIP{ID: 1}
primaryIP := PrimaryIP{ID: 1, IP: net.ParseIP("2001:db8::")}
result, resp, err := env.Client.PrimaryIP.Update(ctx, &primaryIP, opts)
assert.NoError(t, err)
assert.NotNil(t, resp, "no response returned")
assert.Equal(t, *result, primaryIP, "no primary IP returned")
if result.ID != 1 {
t.Errorf("unexpected Primary IP ID: %v", result.ID)
}
assert.Equal(t, primaryIP.IP, result.IP, "parsed the wrong IP")
})
t.Run("Assign", func(t *testing.T) {
env := newTestEnv()
Expand Down
6 changes: 6 additions & 0 deletions hcloud/schema/primary_ip.go
Expand Up @@ -47,3 +47,9 @@ type PrimaryIPGetResult struct {
type PrimaryIPListResult struct {
PrimaryIPs []PrimaryIP `json:"primary_ips"`
}

// PrimaryIPUpdateResult defines the response
// when updating a Primary IP.
type PrimaryIPUpdateResult struct {
PrimaryIP PrimaryIP `json:"primary_ip"`
}

0 comments on commit 7501b60

Please sign in to comment.