Skip to content

Commit 0d588a1

Browse files
committed
feat!: use int64 for ID fields
The `int` datatype is not guaranteed to offer 64 bits of precision. On 32-bit platforms it only has 32 bits of precision. This is incompatible with the Hetzner Cloud identifiers having up to 52-bits after September 1st 2023. See #263 for more details about this change.
1 parent a34a226 commit 0d588a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+253
-228
lines changed

README.md

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# hcloud: A Go library for the Hetzner Cloud API
22

33
[![GitHub Actions status](https://github.com/hetznercloud/hcloud-go/workflows/Continuous%20Integration/badge.svg)](https://github.com/hetznercloud/hcloud-go/actions)
4-
[![GoDoc](https://godoc.org/github.com/hetznercloud/hcloud-go/hcloud?status.svg)](https://godoc.org/github.com/hetznercloud/hcloud-go/hcloud)
4+
[![Go Reference](https://pkg.go.dev/badge/github.com/hetznercloud/hcloud-go/v2/hcloud.svg)](https://pkg.go.dev/github.com/hetznercloud/hcloud-go/v2/hcloud)
55

66
Package hcloud is a library for the Hetzner Cloud API.
77

8-
The library’s documentation is available at [GoDoc](https://godoc.org/github.com/hetznercloud/hcloud-go/hcloud),
8+
The library’s documentation is available at [pkg.go.dev](https://godoc.org/github.com/hetznercloud/hcloud-go/v2/hcloud),
99
the public API documentation is available at [docs.hetzner.cloud](https://docs.hetzner.cloud/).
1010

1111
## Example
@@ -18,7 +18,7 @@ import (
1818
"fmt"
1919
"log"
2020

21-
"github.com/hetznercloud/hcloud-go/hcloud"
21+
"github.com/hetznercloud/hcloud-go/v2/hcloud"
2222
)
2323

2424
func main() {
@@ -36,6 +36,31 @@ func main() {
3636
}
3737
```
3838

39+
## Upgrading
40+
41+
### Support
42+
43+
- `v2` is actively maintained by Hetzner Cloud
44+
- `v1` is supported until September 1st 2023 and will continue to receive new features until then. See [#263](https://github.com/hetznercloud/hcloud-go/issues/263).
45+
46+
### From v1 to v2
47+
48+
Version 2.0.0 was published because we changed the datatype of all `ID` fields from `int` to `int64`.
49+
50+
To migrate to the new version, replace all your imports to reference the new module path:
51+
52+
```diff
53+
import (
54+
- "github.com/hetznercloud/hcloud-go/v2/hcloud"
55+
+ "github.com/hetznercloud/hcloud-go/v2/hcloud"
56+
)
57+
```
58+
59+
When you compile your code, it will show any invalid usages of `int` in your code that you need to fix. We commonly found these changes while updating our integrations:
60+
61+
- `strconv.Atoi(idString)` (parsing integers) needs to be replaced by `strconv.ParseInt(idString, 10, 64)`
62+
- `strconv.Itoa(id)` (formatting integers) needs to be replaced by `strconv.FormatInt(id, 10)`
63+
3964
## Go Version Support
4065

4166
The library supports the latest two Go minor versions, e.g. at the time Go 1.19 is released, it supports Go 1.18 and 1.19.

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/hetznercloud/hcloud-go
1+
module github.com/hetznercloud/hcloud-go/v2
22

33
go 1.19
44

hcloud/action.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import (
66
"net/url"
77
"time"
88

9-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
9+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1010
)
1111

1212
// Action represents an action in the Hetzner Cloud.
1313
type Action struct {
14-
ID int
14+
ID int64
1515
Status ActionStatus
1616
Command string
1717
Progress int
@@ -34,7 +34,7 @@ const (
3434

3535
// ActionResource references other resources from an action.
3636
type ActionResource struct {
37-
ID int
37+
ID int64
3838
Type ActionResourceType
3939
}
4040

@@ -76,7 +76,7 @@ type ActionClient struct {
7676
}
7777

7878
// GetByID retrieves an action by its ID. If the action does not exist, nil is returned.
79-
func (c *ActionClient) GetByID(ctx context.Context, id int) (*Action, *Response, error) {
79+
func (c *ActionClient) GetByID(ctx context.Context, id int64) (*Action, *Response, error) {
8080
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/actions/%d", id), nil)
8181
if err != nil {
8282
return nil, nil, err
@@ -96,7 +96,7 @@ func (c *ActionClient) GetByID(ctx context.Context, id int) (*Action, *Response,
9696
// ActionListOpts specifies options for listing actions.
9797
type ActionListOpts struct {
9898
ListOpts
99-
ID []int
99+
ID []int64
100100
Status []ActionStatus
101101
Sort []string
102102
}
@@ -189,8 +189,8 @@ func (c *ActionClient) WatchOverallProgress(ctx context.Context, actions []*Acti
189189
defer close(errCh)
190190
defer close(progressCh)
191191

192-
successIDs := make([]int, 0, len(actions))
193-
watchIDs := make(map[int]struct{}, len(actions))
192+
successIDs := make([]int64, 0, len(actions))
193+
watchIDs := make(map[int64]struct{}, len(actions))
194194
for _, action := range actions {
195195
watchIDs[action.ID] = struct{}{}
196196
}

hcloud/action_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"testing"
1010
"time"
1111

12-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
12+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1313
)
1414

1515
func TestActionClientGetByID(t *testing.T) {

hcloud/certificate.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"strconv"
1111
"time"
1212

13-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
13+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1414
)
1515

1616
// CertificateType is the type of available certificate types.
@@ -50,7 +50,7 @@ const (
5050

5151
// CertificateUsedByRef points to a resource that uses this certificate.
5252
type CertificateUsedByRef struct {
53-
ID int
53+
ID int64
5454
Type CertificateUsedByRefType
5555
}
5656

@@ -70,7 +70,7 @@ func (st *CertificateStatus) IsFailed() bool {
7070

7171
// Certificate represents a certificate in the Hetzner Cloud.
7272
type Certificate struct {
73-
ID int
73+
ID int64
7474
Name string
7575
Labels map[string]string
7676
Type CertificateType
@@ -96,7 +96,7 @@ type CertificateClient struct {
9696
}
9797

9898
// GetByID retrieves a Certificate by its ID. If the Certificate does not exist, nil is returned.
99-
func (c *CertificateClient) GetByID(ctx context.Context, id int) (*Certificate, *Response, error) {
99+
func (c *CertificateClient) GetByID(ctx context.Context, id int64) (*Certificate, *Response, error) {
100100
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/certificates/%d", id), nil)
101101
if err != nil {
102102
return nil, nil, err
@@ -128,7 +128,7 @@ func (c *CertificateClient) GetByName(ctx context.Context, name string) (*Certif
128128
// Get retrieves a Certificate by its ID if the input can be parsed as an integer, otherwise it
129129
// retrieves a Certificate by its name. If the Certificate does not exist, nil is returned.
130130
func (c *CertificateClient) Get(ctx context.Context, idOrName string) (*Certificate, *Response, error) {
131-
if id, err := strconv.Atoi(idOrName); err == nil {
131+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
132132
return c.GetByID(ctx, id)
133133
}
134134
return c.GetByName(ctx, idOrName)

hcloud/certificate_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/google/go-cmp/cmp"
1010
"github.com/stretchr/testify/assert"
1111

12-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
12+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1313
)
1414

1515
func TestCertificateCreateOptsValidate_Uploaded(t *testing.T) {

hcloud/client.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import (
1818
"github.com/prometheus/client_golang/prometheus"
1919
"golang.org/x/net/http/httpguts"
2020

21-
"github.com/hetznercloud/hcloud-go/hcloud/internal/instrumentation"
22-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
21+
"github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation"
22+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
2323
)
2424

2525
// Endpoint is the base URL of the API.

hcloud/client_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"testing"
1313
"time"
1414

15-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
15+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1616
)
1717

1818
type testEnv struct {

hcloud/datacenter.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import (
66
"net/url"
77
"strconv"
88

9-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
9+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1010
)
1111

1212
// Datacenter represents a datacenter in the Hetzner Cloud.
1313
type Datacenter struct {
14-
ID int
14+
ID int64
1515
Name string
1616
Description string
1717
Location *Location
@@ -30,7 +30,7 @@ type DatacenterClient struct {
3030
}
3131

3232
// GetByID retrieves a datacenter by its ID. If the datacenter does not exist, nil is returned.
33-
func (c *DatacenterClient) GetByID(ctx context.Context, id int) (*Datacenter, *Response, error) {
33+
func (c *DatacenterClient) GetByID(ctx context.Context, id int64) (*Datacenter, *Response, error) {
3434
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/datacenters/%d", id), nil)
3535
if err != nil {
3636
return nil, nil, err
@@ -62,8 +62,8 @@ func (c *DatacenterClient) GetByName(ctx context.Context, name string) (*Datacen
6262
// Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it
6363
// retrieves a datacenter by its name. If the datacenter does not exist, nil is returned.
6464
func (c *DatacenterClient) Get(ctx context.Context, idOrName string) (*Datacenter, *Response, error) {
65-
if id, err := strconv.Atoi(idOrName); err == nil {
66-
return c.GetByID(ctx, int(id))
65+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
66+
return c.GetByID(ctx, id)
6767
}
6868
return c.GetByName(ctx, idOrName)
6969
}

hcloud/datacenter_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"net/http"
77
"testing"
88

9-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
9+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1010
)
1111

1212
func TestDatacenterClient(t *testing.T) {

hcloud/firewall.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import (
1111
"strconv"
1212
"time"
1313

14-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
14+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1515
)
1616

1717
// Firewall represents a Firewall in the Hetzner Cloud.
1818
type Firewall struct {
19-
ID int
19+
ID int64
2020
Name string
2121
Labels map[string]string
2222
Created time.Time
@@ -80,7 +80,7 @@ type FirewallResource struct {
8080

8181
// FirewallResourceServer represents a Server to apply a Firewall on.
8282
type FirewallResourceServer struct {
83-
ID int
83+
ID int64
8484
}
8585

8686
// FirewallResourceLabelSelector represents a LabelSelector to apply a Firewall on.
@@ -94,7 +94,7 @@ type FirewallClient struct {
9494
}
9595

9696
// GetByID retrieves a Firewall by its ID. If the Firewall does not exist, nil is returned.
97-
func (c *FirewallClient) GetByID(ctx context.Context, id int) (*Firewall, *Response, error) {
97+
func (c *FirewallClient) GetByID(ctx context.Context, id int64) (*Firewall, *Response, error) {
9898
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/firewalls/%d", id), nil)
9999
if err != nil {
100100
return nil, nil, err
@@ -126,7 +126,7 @@ func (c *FirewallClient) GetByName(ctx context.Context, name string) (*Firewall,
126126
// Get retrieves a Firewall by its ID if the input can be parsed as an integer, otherwise it
127127
// retrieves a Firewall by its name. If the Firewall does not exist, nil is returned.
128128
func (c *FirewallClient) Get(ctx context.Context, idOrName string) (*Firewall, *Response, error) {
129-
if id, err := strconv.Atoi(idOrName); err == nil {
129+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
130130
return c.GetByID(ctx, id)
131131
}
132132
return c.GetByName(ctx, idOrName)

hcloud/firewall_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
"github.com/google/go-cmp/cmp"
1111

12-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
12+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1313
)
1414

1515
func TestFirewallCreateOptsValidate(t *testing.T) {

hcloud/floating_ip.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import (
1111
"strconv"
1212
"time"
1313

14-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
14+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1515
)
1616

1717
// FloatingIP represents a Floating IP in the Hetzner Cloud.
1818
type FloatingIP struct {
19-
ID int
19+
ID int64
2020
Description string
2121
Created time.Time
2222
IP net.IP
@@ -95,7 +95,7 @@ type FloatingIPClient struct {
9595

9696
// GetByID retrieves a Floating IP by its ID. If the Floating IP does not exist,
9797
// nil is returned.
98-
func (c *FloatingIPClient) GetByID(ctx context.Context, id int) (*FloatingIP, *Response, error) {
98+
func (c *FloatingIPClient) GetByID(ctx context.Context, id int64) (*FloatingIP, *Response, error) {
9999
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/floating_ips/%d", id), nil)
100100
if err != nil {
101101
return nil, nil, err
@@ -127,7 +127,7 @@ func (c *FloatingIPClient) GetByName(ctx context.Context, name string) (*Floatin
127127
// Get retrieves a Floating IP by its ID if the input can be parsed as an integer, otherwise it
128128
// retrieves a Floating IP by its name. If the Floating IP does not exist, nil is returned.
129129
func (c *FloatingIPClient) Get(ctx context.Context, idOrName string) (*FloatingIP, *Response, error) {
130-
if id, err := strconv.Atoi(idOrName); err == nil {
130+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
131131
return c.GetByID(ctx, id)
132132
}
133133
return c.GetByName(ctx, idOrName)

hcloud/floating_ip_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"net/http"
77
"testing"
88

9-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
9+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1010
)
1111

1212
func TestFloatingIPClientGetByID(t *testing.T) {

hcloud/hcloud_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"fmt"
66
"log"
77

8-
"github.com/hetznercloud/hcloud-go/hcloud"
8+
"github.com/hetznercloud/hcloud-go/v2/hcloud"
99
)
1010

1111
func Example() {

hcloud/image.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import (
99
"strconv"
1010
"time"
1111

12-
"github.com/hetznercloud/hcloud-go/hcloud/schema"
12+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1313
)
1414

1515
// Image represents an Image in the Hetzner Cloud.
1616
type Image struct {
17-
ID int
17+
ID int64
1818
Name string
1919
Type ImageType
2020
Status ImageStatus
@@ -81,7 +81,7 @@ type ImageClient struct {
8181
}
8282

8383
// GetByID retrieves an image by its ID. If the image does not exist, nil is returned.
84-
func (c *ImageClient) GetByID(ctx context.Context, id int) (*Image, *Response, error) {
84+
func (c *ImageClient) GetByID(ctx context.Context, id int64) (*Image, *Response, error) {
8585
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/images/%d", id), nil)
8686
if err != nil {
8787
return nil, nil, err
@@ -132,7 +132,7 @@ func (c *ImageClient) GetByNameAndArchitecture(ctx context.Context, name string,
132132
//
133133
// Deprecated: Use [ImageClient.GetForArchitecture] instead.
134134
func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Response, error) {
135-
if id, err := strconv.Atoi(idOrName); err == nil {
135+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
136136
return c.GetByID(ctx, id)
137137
}
138138
return c.GetByName(ctx, idOrName)
@@ -144,7 +144,7 @@ func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Respon
144144
// In contrast to [ImageClient.Get], this method also returns deprecated images. Depending on your needs you should
145145
// check for this in your calling method.
146146
func (c *ImageClient) GetForArchitecture(ctx context.Context, idOrName string, architecture Architecture) (*Image, *Response, error) {
147-
if id, err := strconv.Atoi(idOrName); err == nil {
147+
if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil {
148148
return c.GetByID(ctx, id)
149149
}
150150
return c.GetByNameAndArchitecture(ctx, idOrName, architecture)
@@ -168,7 +168,7 @@ func (l ImageListOpts) values() url.Values {
168168
vals.Add("type", string(typ))
169169
}
170170
if l.BoundTo != nil {
171-
vals.Add("bound_to", strconv.Itoa(l.BoundTo.ID))
171+
vals.Add("bound_to", strconv.FormatInt(l.BoundTo.ID, 10))
172172
}
173173
if l.Name != "" {
174174
vals.Add("name", l.Name)

0 commit comments

Comments
 (0)