New Upstream Release - golang-github-hetznercloud-hcloud-go

Ready changes

Summary

Merged new upstream version: 1.41.0+ds (was: 1.35.3).

Diff

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..d0adea7
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @hetznercloud/integrations
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 87533d9..d049085 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,13 +6,13 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        go-version: [1.17, 1.18, 1.19]
+        go-version: ["1.19", "1.20"]
     steps:
     - name: Set up Go ${{ matrix.go-version }}
-      uses: actions/setup-go@v2
+      uses: actions/setup-go@v3
       with:
         go-version: ${{ matrix.go-version }}
     - name: Check out code into the Go module directory
-      uses: actions/checkout@v1
+      uses: actions/checkout@v3
     - name: Run tests
       run: go test -v ./...
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 88bb867..ed6d26c 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -12,9 +12,9 @@ jobs:
     name: lint
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - name: golangci-lint
-        uses: golangci/golangci-lint-action@v2
+        uses: golangci/golangci-lint-action@v3
         with:
           # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
           version: latest
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
new file mode 100644
index 0000000..24c58c5
--- /dev/null
+++ b/.github/workflows/release-please.yml
@@ -0,0 +1,20 @@
+on:
+  push:
+    branches:
+      - main
+name: release-please
+
+jobs:
+  release-please:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: google-github-actions/release-please-action@v3
+        with:
+          release-type: go
+          package-name: hcloud-go
+
+          # hcloud-go is consumed directly from the git tag.
+          # To make sure that the version in the user-agent is up-to-date,
+          # we need to write it to a file that is included in the git tag.
+          extra-files: |
+            hcloud/hcloud.go
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 69e16b3..0000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: Release Changelog
-on:
-  push:
-    tags:
-      - '*'
-jobs:
-  build:
-    name: Build
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v2
-        with:
-          fetch-depth: 0
-      - name: Set up Go
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.19
-      - name: Run GoReleaser
-        uses: goreleaser/goreleaser-action@v2
-        with:
-          distribution: goreleaser
-          version: latest
-          args: release --rm-dist
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f95e854..6d5d5a9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,17 +11,13 @@ test:golangci-lint:
     - golangci-lint run -v
   except:
     - tags
-    - master
-  tags:
-    - hc-bladerunner
+    - main
 
 test:tests:
   stage: test
-  image: golang:1.18
+  image: golang:1.20
   script:
     - go test -v -race ./...
   except:
     - tags
-    - master
-  tags:
-    - hc-bladerunner
+    - main
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
new file mode 100644
index 0000000..4639129
--- /dev/null
+++ b/.gitlab/CODEOWNERS
@@ -0,0 +1 @@
+* @cloud/integrations
diff --git a/.golangci.yaml b/.golangci.yaml
index 3e86fc8..ef87e03 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -4,6 +4,11 @@ linters-settings:
     exclude: ./.errcheck_excludes.txt
   exhaustive:
     default-signifies-exhaustive: true
+  gci:
+    sections:
+      - standard
+      - default
+      - prefix(github.com/hetznercloud)
   gomodguard:
     blocked:
       modules:
@@ -27,13 +32,15 @@ linters:
   disable-all: true
   enable:
     - bodyclose
-    - deadcode
     - depguard
     - errcheck
+    - errname
     - exhaustive
+    - exportloopref
+    - gci
     - gocritic
+    - godot
     - goimports
-    - golint
     - gomodguard
     - gosec
     - gosimple
@@ -41,14 +48,11 @@ linters:
     - ineffassign
     - misspell
     - prealloc
-    - rowserrcheck
-    - scopelint
+    - revive
     - staticcheck
-    - structcheck
     - typecheck
     - unparam
     - unused
-    - varcheck
     - whitespace
 
 issues:
@@ -56,8 +60,4 @@ issues:
     - path: _test\.go
       linters:
         - gosec
-        - scopelint
         - errcheck
-    - linters:
-        - gosec
-      text: "G204:"
diff --git a/.goreleaser.yml b/.goreleaser.yml
deleted file mode 100644
index f1f8e5d..0000000
--- a/.goreleaser.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-builds:
-  - skip: true
-changelog:
-  sort: asc
-  filters:
-    exclude:
-      - '^docs:'
-      - '^test:'
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..3714529
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,361 @@
+# Changelog
+
+## [1.41.0](https://github.com/hetznercloud/hcloud-go/compare/v1.40.0...v1.41.0) (2023-03-06)
+
+
+### Features
+
+* add ServerClient.RebuildWithResult to return root password ([#245](https://github.com/hetznercloud/hcloud-go/issues/245)) ([82f97cf](https://github.com/hetznercloud/hcloud-go/commit/82f97cf48695848e2569b38f8ff24bb050966ee4))
+
+
+### Bug Fixes
+
+* **deps:** update module github.com/google/go-cmp to v0.5.9 ([#237](https://github.com/hetznercloud/hcloud-go/issues/237)) ([2237ff7](https://github.com/hetznercloud/hcloud-go/commit/2237ff795cbaf1e75759cdd396b3dfe5491c0e24))
+* **deps:** update module github.com/prometheus/client_golang to v1.14.0 ([#241](https://github.com/hetznercloud/hcloud-go/issues/241)) ([75a4a01](https://github.com/hetznercloud/hcloud-go/commit/75a4a0140216eb476990e50ab9b13b60881404be))
+* **deps:** update module github.com/stretchr/testify to v1.8.2 ([#242](https://github.com/hetznercloud/hcloud-go/issues/242)) ([4b51f1e](https://github.com/hetznercloud/hcloud-go/commit/4b51f1e8a13f1f859211910f1dce2daebb583b04))
+* **deps:** update module golang.org/x/net to v0.7.0 [security] ([#236](https://github.com/hetznercloud/hcloud-go/issues/236)) ([774a560](https://github.com/hetznercloud/hcloud-go/commit/774a560b3d167c5c55cd3cbc4f83872ecc878670))
+* **deps:** update module golang.org/x/net to v0.8.0 ([#243](https://github.com/hetznercloud/hcloud-go/issues/243)) ([8ae14f3](https://github.com/hetznercloud/hcloud-go/commit/8ae14f36021a32f5bab21a74d2467aa2487b348d))
+
+## [1.40.0](https://github.com/hetznercloud/hcloud-go/compare/v1.39.0...v1.40.0) (2023-02-08)
+
+
+### Features
+
+* **action:** use configurable backoff to wait for action progress ([#227](https://github.com/hetznercloud/hcloud-go/issues/227)) ([8da6417](https://github.com/hetznercloud/hcloud-go/commit/8da6417cf7d87bf44117ede9cd2839d7dc055f66))
+* support go v1.20 and drop v1.18 ([#231](https://github.com/hetznercloud/hcloud-go/issues/231)) ([44af6e5](https://github.com/hetznercloud/hcloud-go/commit/44af6e5beade11432b5ca30575781875cbd08343))
+
+## [1.39.0](https://github.com/hetznercloud/hcloud-go/compare/v1.38.0...v1.39.0) (2022-12-29)
+
+
+### Features
+
+* Use generics to get pointers to types ([#219](https://github.com/hetznercloud/hcloud-go/issues/219)) ([a5cd797](https://github.com/hetznercloud/hcloud-go/commit/a5cd79782dc849b3137e46ada2da6b319d4093c8))
+
+
+### Bug Fixes
+
+* deprecate PricingPrimaryIPTypePrice.Datacenter for Location ([#222](https://github.com/hetznercloud/hcloud-go/issues/222)) ([e0e5a1e](https://github.com/hetznercloud/hcloud-go/commit/e0e5a1e08fd7c0864fd94a787ee86714b5e9afc5))
+
+## v1.38.0
+
+### What's Changed
+* feat(network): add new Network Zone us-west by @apricote in https://github.com/hetznercloud/hcloud-go/pull/217
+* chore: prepare v1.38.0 by @apricote in https://github.com/hetznercloud/hcloud-go/pull/218
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.37.0...v1.38.0
+
+## v1.37.0
+
+### What's Changed
+* PrimaryIPClient Add AllWithOpts by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/214
+* fix: error when updating IPv6 Primary IP by @apricote in https://github.com/hetznercloud/hcloud-go/pull/215
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.36.0...v1.37.0
+
+## v1.36.0
+
+### What's Changed
+* feat: add ServerClient.DeleteWithResult method by @apricote in https://github.com/hetznercloud/hcloud-go/pull/213
+
+### New Contributors
+* @apricote made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/213
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.35.3...v1.36.0
+
+## v1.35.3
+
+### What's Changed
+* Drop support for Go < 1.17 and add official tests on go 1.19 by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/211
+* Stop automatic retrying on RateLimitExceeded by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/210
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.35.2...v1.35.3
+
+## v1.35.2
+
+### What's Changed
+* Allow empty labels by @4ND3R50N in https://github.com/hetznercloud/hcloud-go/pull/207
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.35.1...v1.35.2
+
+## v1.35.1
+
+### What's Changed
+* Accept no primary IPs with server create with StartAfterCreate = false by @4ND3R50N in https://github.com/hetznercloud/hcloud-go/pull/205
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.35.0...v1.35.1
+
+## v1.35.0
+
+### What's Changed
+* Catch invalid token values and error out without value exposure by @NotTheEvilOne in https://github.com/hetznercloud/hcloud-go/pull/194
+* Remove ServerRescueTypeFreeBSD64 by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/203
+* Add Primary IP Support by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/204
+
+### New Contributors
+* @NotTheEvilOne made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/194
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.34.0...v1.35.0
+
+## v1.34.0
+
+### What's Changed
+* Test on Go 1.18 by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/202
+* Add support for sorting the response of all list calls by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/201
+* Set UsePrivateIP for targets when creating a LoadBalancer by @hakman in https://github.com/hetznercloud/hcloud-go/pull/198
+
+### New Contributors
+* @hakman made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/198
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.33.2...v1.34.0
+
+## v1.33.2
+
+### What's Changed
+* Add constant for resource locked error code by @patrickschaffrath in https://github.com/hetznercloud/hcloud-go/pull/189
+* Fix metadata client error detection by @choffmeister in https://github.com/hetznercloud/hcloud-go/pull/193
+* Add labels.go to validate resource labels by @4ND3R50N in https://github.com/hetznercloud/hcloud-go/pull/197
+
+### New Contributors
+* @patrickschaffrath made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/189
+* @choffmeister made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/193
+* @4ND3R50N made their first contribution in https://github.com/hetznercloud/hcloud-go/pull/197
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.33.1...v1.33.2
+
+## v1.33.1
+
+### Changelog
+
+41fef2f Add constants for new firewall error code
+
+## v1.33.0
+
+### What's Changed
+* Add us-east network zone by @LKaemmerling in https://github.com/hetznercloud/hcloud-go/pull/187
+
+
+**Full Changelog**: https://github.com/hetznercloud/hcloud-go/compare/v1.32.0...v1.33.0
+
+## v1.32.0
+
+### Changelog
+
+785896c Add Metadata Client (#184)
+7778143 Bump version to 1.32.0
+eabe683 Make it possible to instrument the hcloud-go (#185)
+
+## v1.31.1
+
+### Changelog
+
+1cde0d7 Add RDNS client (#183)
+
+## v1.31.0
+
+### Changelog
+
+0656bf9 Add support for Load Balancer DNS PTRs (#182)
+9218970 Bump hcloud.Version
+ebf9f25 Test on/with go 1.17 (#181)
+
+## v1.30.0
+
+### Changelog
+
+592b198 Add new Floating IP Pricing structure (#180)
+c43897a Bump hcloud.Version
+ab0ebb2 Placement groups (#179)
+
+## v1.29.1
+
+### Changelog
+
+e951e99 Fix firewall rule description
+
+## v1.29.0
+
+### Changelog
+
+e3eca12 Add description field to firewall rules (#177)
+
+## v1.28.0
+
+### Changelog
+
+ae5e1b8 Add goreleaser (#175)
+4cf75f4 Add support for app images (#176)
+
+## v1.27.0
+
+Add support for firewall protocols ESP and GRE (#173) 
+
+## v1.26.2
+
+- Fix AppliedTo Field in FirewallCreateRequest
+- Add `deleted` and `IsDeleted()` to `Image` (https://github.com/hetznercloud/hcloud-go/pull/172)
+
+## v1.26.1
+
+- Fix validation error caused by firewall label selectors (https://github.com/hetznercloud/hcloud-go/pull/171)
+
+## v1.26.0
+
+- Add Firewall Resource Label Selector (#169)
+
+## v1.25.0
+
+* Support Hetzner Cloud managed Certificates (#167)
+
+## v1.23.1
+* Add removed `ErrorCodeServerAlreadyAttached` again
+
+## v1.23.0
+
+* Add missing constants for all resource specific error codes
+* Expose metrics for Servers and Load Balancers
+* Add support for vSwitch Subnetworks
+
+## v1.22.0
+
+* Add `PrimaryDiskSize` Field to `Server`
+
+## v1.21.1
+
+* Don't send `Authorization` Header when `WithToken` was not called
+
+## v1.21.0
+
+* Add `IncludeDeprecated` Field to `ImageListOpts`
+
+## v1.20.0
+
+* Add support for Load Balancer Label Selector targets
+* Add support for Load Balancer IP targets
+
+## v1.19.0
+
+* 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
+* Fix retrying of requests that contain a body
+
+## v1.18.2
+
+* Retry API requests on conflict error
+
+## v1.18.1
+
+* Make all `GetByName` methods return `nil` when an empty name is provided
+* Clarify that filters specified in options for List() calls are not taken
+  into account when their value corresponds to their zero value or when
+  they are empty.
+
+## v1.18.0
+
+* Add `Status` field to `Volume`
+* Add subnet type `cloud`
+* Add `WithHTTPClient` option to specify a custom `http.Client`
+* Add API for requesting a VNC console
+* Add support for load balancers and certificates (beta)
+
+## v1.17.0
+
+* Add `Created` field to `SSHKey`
+
+## v1.16.0
+
+* Make IP range optional when adding a subnet to a network
+* Add support for names to Floating IPs
+
+## v1.15.1
+
+* Rename `MacAddress` to `MACAddress` on `ServerPrivateNet`
+
+## v1.15.0
+
+* Add `MacAddress` field to `ServerPrivateNet`
+* Add `WithDebugWriter()` client option to provide an `io.Writer` to write debug output to
+
+## v1.14.0
+
+* Add `Created` field to `FloatingIP`
+* Add support for networks
+
+## v1.13.0
+
+* Add missing fields to `*ListOpts` structs
+* Fix error handling in `WatchProgress()`
+* Add support for filtering volumes, images, and servers by status
+
+## v1.12.0
+
+* Add missing constants for all [documented error codes](https://docs.hetzner.cloud/#overview-errors)
+* Add support for automounting volumes
+* Add support for attaching volumes when creating a server
+
+## v1.11.0
+
+* Add `NextActions` to `ServerCreateResult` and `VolumeCreateResult`
+
+## v1.10.0
+
+* Add `WithApplication()` client option to provide an application name and version
+  that will be included in the `User-Agent` HTTP header
+* Add support for volumes
+
+## v1.9.0
+
+* Add `AllWithOpts()` to server, Floating IP, image, and SSH key client
+* Expose labels of servers, Floating IPs, images, and SSH Keys
+
+## v1.8.0
+
+* Add `WithPollInterval()` option to `Client` which allows to specify the polling interval
+  ([issue #92](https://github.com/hetznercloud/hcloud-go/issues/92))
+* Add `CPUType` field to `ServerType` ([issue #91](https://github.com/hetznercloud/hcloud-go/pull/91))
+
+## v1.7.0
+
+* Add `Deprecated ` field to `Image` ([issue #88](https://github.com/hetznercloud/hcloud-go/issues/88))
+* Add `StartAfterCreate` flag to `ServerCreateOpts` ([issue #87](https://github.com/hetznercloud/hcloud-go/issues/87))
+* Fix enum types ([issue #89](https://github.com/hetznercloud/hcloud-go/issues/89))
+
+## v1.6.0
+
+* Add `ChangeProtection()` to server, Floating IP, and image client
+* Expose protection of servers, Floating IPs, and images
+
+## v1.5.0
+
+* Add `GetByFingerprint()` to SSH key client
+
+## v1.4.0
+
+* Retry all calls that triggered the API ratelimit
+* Slow down `WatchProgress()` in action client from 100ms polling interval to 500ms
+
+## v1.3.1
+
+* Make clients using the old error code for ratelimiting work as expected
+  ([issue #73](https://github.com/hetznercloud/hcloud-go/issues/73))
+
+## v1.3.0
+
+* Support passing user data on server creation ([issue #70](https://github.com/hetznercloud/hcloud-go/issues/70))
+* Fix leaking response body by not closing it ([issue #68](https://github.com/hetznercloud/hcloud-go/issues/68))
+
+## v1.2.0
+
+* Add `WatchProgress()` to action client
+* Use correct error code for ratelimit error (deprecated
+  `ErrorCodeLimitReached`, added `ErrorCodeRateLimitExceeded`)
+
+## v1.1.0
+
+* Add `Image` field to `Server`
diff --git a/CHANGES.md b/CHANGES.md
deleted file mode 100644
index efa8015..0000000
--- a/CHANGES.md
+++ /dev/null
@@ -1,152 +0,0 @@
-# Changes
-
-As of release v1.24.0 we moved the release notes to Github Releases: https://github.com/hetznercloud/hcloud-go/releases
-
-## v1.23.1
-* Add removed `ErrorCodeServerAlreadyAttached` again
-
-## v1.23.0
-
-* Add missing constants for all resource specific error codes
-* Expose metrics for Servers and Load Balancers
-* Add support for vSwitch Subnetworks
-
-## v1.22.0
-
-* Add `PrimaryDiskSize` Field to `Server`
-
-## v1.21.1
-
-* Don't send `Authorization` Header when `WithToken` was not called
-
-## v1.21.0
-
-* Add `IncludeDeprecated` Field to `ImageListOpts`
-
-## v1.20.0
-
-* Add support for Load Balancer Label Selector targets
-* Add support for Load Balancer IP targets
-
-## v1.19.0
-
-* 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
-* Fix retrying of requests that contain a body
-
-## v1.18.2
-
-* Retry API requests on conflict error
-
-## v1.18.1
-
-* Make all `GetByName` methods return `nil` when an empty name is provided
-* Clarify that filters specified in options for List() calls are not taken
-  into account when their value corresponds to their zero value or when
-  they are empty.
-
-## v1.18.0
-
-* Add `Status` field to `Volume`
-* Add subnet type `cloud`
-* Add `WithHTTPClient` option to specify a custom `http.Client`
-* Add API for requesting a VNC console
-* Add support for load balancers and certificates (beta)
-
-## v1.17.0
-
-* Add `Created` field to `SSHKey`
-
-## v1.16.0
-
-* Make IP range optional when adding a subnet to a network
-* Add support for names to Floating IPs
-
-## v1.15.1
-
-* Rename `MacAddress` to `MACAddress` on `ServerPrivateNet`
-
-## v1.15.0
-
-* Add `MacAddress` field to `ServerPrivateNet`
-* Add `WithDebugWriter()` client option to provide an `io.Writer` to write debug output to
-
-## v1.14.0
-
-* Add `Created` field to `FloatingIP`
-* Add support for networks
-
-## v1.13.0
-
-* Add missing fields to `*ListOpts` structs
-* Fix error handling in `WatchProgress()`
-* Add support for filtering volumes, images, and servers by status
-
-## v1.12.0
-
-* Add missing constants for all [documented error codes](https://docs.hetzner.cloud/#overview-errors)
-* Add support for automounting volumes
-* Add support for attaching volumes when creating a server
-
-## v1.11.0
-
-* Add `NextActions` to `ServerCreateResult` and `VolumeCreateResult`
-
-## v1.10.0
-
-* Add `WithApplication()` client option to provide an application name and version
-  that will be included in the `User-Agent` HTTP header
-* Add support for volumes
-
-## v1.9.0
-
-* Add `AllWithOpts()` to server, Floating IP, image, and SSH key client
-* Expose labels of servers, Floating IPs, images, and SSH Keys
-
-## v1.8.0
-
-* Add `WithPollInterval()` option to `Client` which allows to specify the polling interval
-  ([issue #92](https://github.com/hetznercloud/hcloud-go/issues/92))
-* Add `CPUType` field to `ServerType` ([issue #91](https://github.com/hetznercloud/hcloud-go/pull/91))
-
-## v1.7.0
-
-* Add `Deprecated ` field to `Image` ([issue #88](https://github.com/hetznercloud/hcloud-go/issues/88))
-* Add `StartAfterCreate` flag to `ServerCreateOpts` ([issue #87](https://github.com/hetznercloud/hcloud-go/issues/87))
-* Fix enum types ([issue #89](https://github.com/hetznercloud/hcloud-go/issues/89))
-
-## v1.6.0
-
-* Add `ChangeProtection()` to server, Floating IP, and image client
-* Expose protection of servers, Floating IPs, and images
-
-## v1.5.0
-
-* Add `GetByFingerprint()` to SSH key client
-
-## v1.4.0
-
-* Retry all calls that triggered the API ratelimit
-* Slow down `WatchProgress()` in action client from 100ms polling interval to 500ms
-
-## v1.3.1
-
-* Make clients using the old error code for ratelimiting work as expected
-  ([issue #73](https://github.com/hetznercloud/hcloud-go/issues/73))
-
-## v1.3.0
-
-* Support passing user data on server creation ([issue #70](https://github.com/hetznercloud/hcloud-go/issues/70))
-* Fix leaking response body by not closing it ([issue #68](https://github.com/hetznercloud/hcloud-go/issues/68))
-
-## v1.2.0
-
-* Add `WatchProgress()` to action client
-* Use correct error code for ratelimit error (deprecated
-  `ErrorCodeLimitReached`, added `ErrorCodeRateLimitExceeded`)
-
-## v1.1.0
-
-* Add `Image` field to `Server`
diff --git a/README.md b/README.md
index 2263cb9..238c6ec 100644
--- a/README.md
+++ b/README.md
@@ -36,6 +36,14 @@ func main() {
 }
 ```
 
+## Go Version Support
+
+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.
+
+This matches the official [Go Release Policy](https://go.dev/doc/devel/release#policy).
+
+When the minimum required Go version is changed, it is announced in the release notes for that version.
+
 ## License
 
 MIT license
diff --git a/debian/changelog b/debian/changelog
index a894207..a436289 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-hetznercloud-hcloud-go (1.41.0+ds-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 07 Apr 2023 01:14:03 -0000
+
 golang-github-hetznercloud-hcloud-go (1.35.3-1) unstable; urgency=medium
 
   * New upstream release
diff --git a/go.mod b/go.mod
index 33a3399..900c941 100644
--- a/go.mod
+++ b/go.mod
@@ -1,26 +1,26 @@
 module github.com/hetznercloud/hcloud-go
 
-go 1.18
+go 1.19
 
 require (
-	github.com/google/go-cmp v0.5.5
-	github.com/prometheus/client_golang v1.11.0
-	github.com/stretchr/testify v1.7.0
-	golang.org/x/net v0.0.0-20200625001655-4c5254603344
+	github.com/google/go-cmp v0.5.9
+	github.com/prometheus/client_golang v1.14.0
+	github.com/stretchr/testify v1.8.2
+	golang.org/x/net v0.8.0
 )
 
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/cespare/xxhash/v2 v2.1.1 // indirect
+	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/golang/protobuf v1.4.3 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_model v0.2.0 // indirect
-	github.com/prometheus/common v0.26.0 // indirect
-	github.com/prometheus/procfs v0.6.0 // indirect
-	golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect
-	golang.org/x/text v0.3.2 // indirect
-	google.golang.org/protobuf v1.26.0-rc.1 // indirect
-	gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
+	github.com/prometheus/client_model v0.3.0 // indirect
+	github.com/prometheus/common v0.37.0 // indirect
+	github.com/prometheus/procfs v0.8.0 // indirect
+	golang.org/x/sys v0.6.0 // indirect
+	golang.org/x/text v0.8.0 // indirect
+	google.golang.org/protobuf v1.28.1 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 7b8c252..4e7e279 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,38 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -8,43 +42,105 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -59,6 +155,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -69,81 +166,355 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
+github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
+github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/hcloud/action.go b/hcloud/action.go
index 622f7bf..e915d75 100644
--- a/hcloud/action.go
+++ b/hcloud/action.go
@@ -181,7 +181,24 @@ func (c *ActionClient) AllWithOpts(ctx context.Context, opts ActionListOpts) ([]
 	return allActions, nil
 }
 
-// WatchOverallProgress watches several actions' progress until they complete with success or error.
+// WatchOverallProgress watches several actions' progress until they complete
+// with success or error. This watching happens in a goroutine and updates are
+// provided through the two returned channels:
+//
+//   - The first channel receives percentage updates of the progress, based on
+//     the number of completed versus total watched actions. The return value
+//     is an int between 0 and 100.
+//   - The second channel returned receives errors for actions that did not
+//     complete successfully, as well as any errors that happened while
+//     querying the API.
+//
+// By default the method keeps watching until all actions have finished
+// processing. If you want to be able to cancel the method or configure a
+// timeout, use the [context.Context]. Once the method has stopped watching,
+// both returned channels are closed.
+//
+// WatchOverallProgress uses the [WithPollBackoffFunc] of the [Client] to wait
+// until sending the next request.
 func (c *ActionClient) WatchOverallProgress(ctx context.Context, actions []*Action) (<-chan int, <-chan error) {
 	errCh := make(chan error, len(actions))
 	progressCh := make(chan int)
@@ -196,15 +213,15 @@ func (c *ActionClient) WatchOverallProgress(ctx context.Context, actions []*Acti
 			watchIDs[action.ID] = struct{}{}
 		}
 
-		ticker := time.NewTicker(c.client.pollInterval)
-		defer ticker.Stop()
+		retries := 0
+
 		for {
 			select {
 			case <-ctx.Done():
 				errCh <- ctx.Err()
 				return
-			case <-ticker.C:
-				break
+			case <-time.After(c.client.pollBackoffFunc(retries)):
+				retries++
 			}
 
 			opts := ActionListOpts{}
@@ -241,7 +258,24 @@ func (c *ActionClient) WatchOverallProgress(ctx context.Context, actions []*Acti
 	return progressCh, errCh
 }
 
-// WatchProgress watches one action's progress until it completes with success or error.
+// WatchProgress watches one action's progress until it completes with success
+// or error. This watching happens in a goroutine and updates are provided
+// through the two returned channels:
+//
+//   - The first channel receives percentage updates of the progress, based on
+//     the progress percentage indicated by the API. The return value is an int
+//     between 0 and 100.
+//   - The second channel receives any errors that happened while querying the
+//     API, as well as the error of the action if it did not complete
+//     successfully, or nil if it did.
+//
+// By default the method keeps watching until the action has finished
+// processing. If you want to be able to cancel the method or configure a
+// timeout, use the [context.Context]. Once the method has stopped watching,
+// both returned channels are closed.
+//
+// WatchProgress uses the [WithPollBackoffFunc] of the [Client] to wait until
+// sending the next request.
 func (c *ActionClient) WatchProgress(ctx context.Context, action *Action) (<-chan int, <-chan error) {
 	errCh := make(chan error, 1)
 	progressCh := make(chan int)
@@ -250,16 +284,15 @@ func (c *ActionClient) WatchProgress(ctx context.Context, action *Action) (<-cha
 		defer close(errCh)
 		defer close(progressCh)
 
-		ticker := time.NewTicker(c.client.pollInterval)
-		defer ticker.Stop()
+		retries := 0
 
 		for {
 			select {
 			case <-ctx.Done():
 				errCh <- ctx.Err()
 				return
-			case <-ticker.C:
-				break
+			case <-time.After(c.client.pollBackoffFunc(retries)):
+				retries++
 			}
 
 			a, _, err := c.GetByID(ctx, action.ID)
diff --git a/hcloud/action_test.go b/hcloud/action_test.go
index 28e32f7..660f3de 100644
--- a/hcloud/action_test.go
+++ b/hcloud/action_test.go
@@ -3,7 +3,9 @@ package hcloud
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"net/http"
+	"reflect"
 	"testing"
 	"time"
 
@@ -164,6 +166,126 @@ func TestActionClientAll(t *testing.T) {
 	}
 }
 
+func TestActionClientWatchOverallProgress(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	callCount := 0
+
+	env.Mux.HandleFunc("/actions", func(w http.ResponseWriter, r *http.Request) {
+		callCount++
+		var actions []schema.Action
+
+		switch callCount {
+		case 1:
+			actions = []schema.Action{
+				{
+					ID:       1,
+					Status:   "running",
+					Progress: 50,
+				},
+				{
+					ID:       2,
+					Status:   "running",
+					Progress: 50,
+				},
+			}
+		case 2:
+			actions = []schema.Action{
+				{
+					ID:       1,
+					Status:   "running",
+					Progress: 75,
+				},
+				{
+					ID:       2,
+					Status:   "error",
+					Progress: 100,
+					Error: &schema.ActionError{
+						Code:    "action_failed",
+						Message: "action failed",
+					},
+				},
+			}
+		case 3:
+			actions = []schema.Action{
+				{
+					ID:       1,
+					Status:   "success",
+					Progress: 100,
+				},
+			}
+		default:
+			t.Errorf("unexpected number of calls to the test server: %v", callCount)
+		}
+
+		w.Header().Set("Content-Type", "application/json")
+		_ = json.NewEncoder(w).Encode(struct {
+			Actions []schema.Action `json:"actions"`
+			Meta    schema.Meta     `json:"meta"`
+		}{
+			Actions: actions,
+			Meta: schema.Meta{
+				Pagination: &schema.MetaPagination{
+					Page:         1,
+					LastPage:     1,
+					PerPage:      len(actions),
+					TotalEntries: len(actions),
+				},
+			},
+		})
+	})
+
+	actions := []*Action{
+		{
+			ID:     1,
+			Status: ActionStatusRunning,
+		},
+		{
+			ID:     2,
+			Status: ActionStatusRunning,
+		},
+	}
+
+	ctx := context.Background()
+	progressCh, errCh := env.Client.Action.WatchOverallProgress(ctx, actions)
+	progressUpdates := []int{}
+	errs := []error{}
+
+	moreProgress, moreErrors := true, true
+
+	for moreProgress || moreErrors {
+		var progress int
+		var err error
+
+		select {
+		case progress, moreProgress = <-progressCh:
+			if moreProgress {
+				progressUpdates = append(progressUpdates, progress)
+			}
+		case err, moreErrors = <-errCh:
+			if moreErrors {
+				errs = append(errs, err)
+			}
+		}
+	}
+
+	if len(errs) != 1 {
+		t.Fatalf("expected to receive one error: %v", errs)
+	}
+
+	err := errs[0]
+
+	if e, ok := errors.Unwrap(err).(ActionError); !ok || e.Code != "action_failed" {
+		t.Fatalf("expected hcloud.Error, but got: %#v", err)
+	}
+
+	expectedProgressUpdates := []int{50}
+	if !reflect.DeepEqual(progressUpdates, expectedProgressUpdates) {
+		t.Fatalf("expected progresses %v but received %v", expectedProgressUpdates, progressUpdates)
+	}
+}
+
 func TestActionClientWatchProgress(t *testing.T) {
 	env := newTestEnv()
 	defer env.Teardown()
diff --git a/hcloud/certificate.go b/hcloud/certificate.go
index 04334de..6278552 100644
--- a/hcloud/certificate.go
+++ b/hcloud/certificate.go
@@ -31,10 +31,10 @@ const (
 	CertificateStatusTypePending CertificateStatusType = "pending"
 	CertificateStatusTypeFailed  CertificateStatusType = "failed"
 
-	// only in issuance
+	// only in issuance.
 	CertificateStatusTypeCompleted CertificateStatusType = "completed"
 
-	// only in renewal
+	// only in renewal.
 	CertificateStatusTypeScheduled   CertificateStatusType = "scheduled"
 	CertificateStatusTypeUnavailable CertificateStatusType = "unavailable"
 )
diff --git a/hcloud/certificate_test.go b/hcloud/certificate_test.go
index 055351a..003bcb5 100644
--- a/hcloud/certificate_test.go
+++ b/hcloud/certificate_test.go
@@ -405,7 +405,7 @@ func TestCertificateClientUpdate(t *testing.T) {
 			t.Fatal(err)
 		}
 		expectedReqBody := schema.CertificateUpdateRequest{
-			Name: String("test"),
+			Name: Ptr("test"),
 			Labels: func() *map[string]string {
 				labels := map[string]string{"key": "value"}
 				return &labels
diff --git a/hcloud/client.go b/hcloud/client.go
index 792be9b..f3b5a83 100644
--- a/hcloud/client.go
+++ b/hcloud/client.go
@@ -15,10 +15,11 @@ import (
 	"strings"
 	"time"
 
-	"github.com/hetznercloud/hcloud-go/hcloud/internal/instrumentation"
-	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 	"github.com/prometheus/client_golang/prometheus"
 	"golang.org/x/net/http/httpguts"
+
+	"github.com/hetznercloud/hcloud-go/hcloud/internal/instrumentation"
+	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
 // Endpoint is the base URL of the API.
@@ -42,7 +43,10 @@ func ConstantBackoff(d time.Duration) BackoffFunc {
 }
 
 // ExponentialBackoff returns a BackoffFunc which implements an exponential
-// backoff using the formula: b^retries * d
+// backoff.
+// It uses the formula:
+//
+//	b^retries * d
 func ExponentialBackoff(b float64, d time.Duration) BackoffFunc {
 	return func(retries int) time.Duration {
 		return time.Duration(math.Pow(b, float64(retries))) * d
@@ -54,8 +58,8 @@ type Client struct {
 	endpoint                string
 	token                   string
 	tokenValid              bool
-	pollInterval            time.Duration
 	backoffFunc             BackoffFunc
+	pollBackoffFunc         BackoffFunc
 	httpClient              *http.Client
 	applicationName         string
 	applicationVersion      string
@@ -102,15 +106,31 @@ func WithToken(token string) ClientOption {
 	}
 }
 
-// WithPollInterval configures a Client to use the specified interval when polling
-// from the API.
+// WithPollInterval configures a Client to use the specified interval when
+// polling from the API.
+//
+// Deprecated: Setting the poll interval is deprecated, you can now configure
+// [WithPollBackoffFunc] with a [ConstantBackoff] to get the same results. To
+// migrate your code, replace your usage like this:
+//
+//	// before
+//	hcloud.WithPollInterval(2 * time.Second)
+//	// now
+//	hcloud.WithPollBackoffFunc(hcloud.ConstantBackoff(2 * time.Second))
 func WithPollInterval(pollInterval time.Duration) ClientOption {
+	return WithPollBackoffFunc(ConstantBackoff(pollInterval))
+}
+
+// WithPollBackoffFunc configures a Client to use the specified backoff
+// function when polling from the API.
+func WithPollBackoffFunc(f BackoffFunc) ClientOption {
 	return func(client *Client) {
-		client.pollInterval = pollInterval
+		client.backoffFunc = f
 	}
 }
 
 // WithBackoffFunc configures a Client to use the specified backoff function.
+// The backoff function is used for retrying HTTP requests.
 func WithBackoffFunc(f BackoffFunc) ClientOption {
 	return func(client *Client) {
 		client.backoffFunc = f
@@ -152,11 +172,11 @@ func WithInstrumentation(registry *prometheus.Registry) ClientOption {
 // NewClient creates a new client.
 func NewClient(options ...ClientOption) *Client {
 	client := &Client{
-		endpoint:     Endpoint,
-		tokenValid:   true,
-		httpClient:   &http.Client{},
-		backoffFunc:  ExponentialBackoff(2, 500*time.Millisecond),
-		pollInterval: 500 * time.Millisecond,
+		endpoint:        Endpoint,
+		tokenValid:      true,
+		httpClient:      &http.Client{},
+		backoffFunc:     ExponentialBackoff(2, 500*time.Millisecond),
+		pollBackoffFunc: ConstantBackoff(500 * time.Millisecond),
 	}
 
 	for _, option := range options {
diff --git a/hcloud/client_test.go b/hcloud/client_test.go
index e6d804b..e4df032 100644
--- a/hcloud/client_test.go
+++ b/hcloud/client_test.go
@@ -35,6 +35,7 @@ func newTestEnv() testEnv {
 		WithEndpoint(server.URL),
 		WithToken("token"),
 		WithBackoffFunc(func(_ int) time.Duration { return 0 }),
+		WithPollBackoffFunc(func(r int) time.Duration { return 0 }),
 	)
 	return testEnv{
 		Server: server,
diff --git a/hcloud/error.go b/hcloud/error.go
index c15581b..ff04d07 100644
--- a/hcloud/error.go
+++ b/hcloud/error.go
@@ -28,14 +28,14 @@ const (
 	ErrorCodeResourceLocked        ErrorCode = "resource_locked"         // The resource is locked. The caller should contact support
 	ErrorUnsupportedError          ErrorCode = "unsupported_error"       // The given resource does not support this
 
-	// Server related error codes
+	// Server related error codes.
 	ErrorCodeInvalidServerType     ErrorCode = "invalid_server_type"     // The server type does not fit for the given server or is deprecated
 	ErrorCodeServerNotStopped      ErrorCode = "server_not_stopped"      // The action requires a stopped server
 	ErrorCodeNetworksOverlap       ErrorCode = "networks_overlap"        // The network IP range overlaps with one of the server networks
 	ErrorCodePlacementError        ErrorCode = "placement_error"         // An error during the placement occurred
 	ErrorCodeServerAlreadyAttached ErrorCode = "server_already_attached" // The server is already attached to the resource
 
-	// Load Balancer related error codes
+	// Load Balancer related error codes.
 	ErrorCodeIPNotOwned                       ErrorCode = "ip_not_owned"                          // The IP you are trying to add as a target is not owned by the Project owner
 	ErrorCodeSourcePortAlreadyUsed            ErrorCode = "source_port_already_used"              // The source port you are trying to add is already in use
 	ErrorCodeCloudResourceIPNotAllowed        ErrorCode = "cloud_resource_ip_not_allowed"         // The IP you are trying to add as a target belongs to a Hetzner Cloud resource
@@ -46,16 +46,16 @@ const (
 	ErrorCodeTargetsWithoutUsePrivateIP       ErrorCode = "targets_without_use_private_ip"        // The Load Balancer has targets that use the public IP instead of the private IP
 	ErrorCodeLoadBalancerNotAttachedToNetwork ErrorCode = "load_balancer_not_attached_to_network" // The Load Balancer is not attached to a network
 
-	// Network related error codes
+	// Network related error codes.
 	ErrorCodeIPNotAvailable     ErrorCode = "ip_not_available"        // The provided Network IP is not available
 	ErrorCodeNoSubnetAvailable  ErrorCode = "no_subnet_available"     // No Subnet or IP is available for the Load Balancer/Server within the network
 	ErrorCodeVSwitchAlreadyUsed ErrorCode = "vswitch_id_already_used" // The given Robot vSwitch ID is already registered in another network
 
-	// Volume related error codes
+	// Volume related error codes.
 	ErrorCodeNoSpaceLeftInLocation ErrorCode = "no_space_left_in_location" // There is no volume space left in the given location
 	ErrorCodeVolumeAlreadyAttached ErrorCode = "volume_already_attached"   // Volume is already attached to a server, detach first
 
-	// Firewall related error codes
+	// Firewall related error codes.
 	ErrorCodeFirewallAlreadyApplied   ErrorCode = "firewall_already_applied"    // Firewall was already applied on resource
 	ErrorCodeFirewallAlreadyRemoved   ErrorCode = "firewall_already_removed"    // Firewall was already removed from the resource
 	ErrorCodeIncompatibleNetworkType  ErrorCode = "incompatible_network_type"   // The Network type is incompatible for the given resource
@@ -63,7 +63,7 @@ const (
 	ErrorCodeServerAlreadyAdded       ErrorCode = "server_already_added"        // Server added more than one time to resource
 	ErrorCodeFirewallResourceNotFound ErrorCode = "firewall_resource_not_found" // Resource a firewall should be attached to / detached from not found
 
-	// Certificate related error codes
+	// Certificate related error codes.
 	ErrorCodeCAARecordDoesNotAllowCA                        ErrorCode = "caa_record_does_not_allow_ca"                          // CAA record does not allow certificate authority
 	ErrorCodeCADNSValidationFailed                          ErrorCode = "ca_dns_validation_failed"                              // Certificate Authority: DNS validation failed
 	ErrorCodeCATooManyAuthorizationsFailedRecently          ErrorCode = "ca_too_many_authorizations_failed_recently"            // Certificate Authority: Too many authorizations failed recently
diff --git a/hcloud/firewall_test.go b/hcloud/firewall_test.go
index bdda89d..3353148 100644
--- a/hcloud/firewall_test.go
+++ b/hcloud/firewall_test.go
@@ -8,6 +8,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
@@ -281,7 +282,7 @@ func TestFirewallClientUpdate(t *testing.T) {
 			t.Fatal(err)
 		}
 		expectedReqBody := schema.FirewallUpdateRequest{
-			Name: String("test"),
+			Name: Ptr("test"),
 			Labels: func() *map[string]string {
 				labels := map[string]string{"key": "value"}
 				return &labels
diff --git a/hcloud/floating_ip.go b/hcloud/floating_ip.go
index b180409..e2643a6 100644
--- a/hcloud/floating_ip.go
+++ b/hcloud/floating_ip.go
@@ -32,7 +32,7 @@ type FloatingIP struct {
 }
 
 // DNSPtrForIP returns the reverse DNS pointer of the IP address.
-// Deprecated: Use GetDNSPtrForIP instead
+// Deprecated: Use GetDNSPtrForIP instead.
 func (f *FloatingIP) DNSPtrForIP(ip net.IP) string {
 	return f.DNSPtr[ip.String()]
 }
@@ -241,10 +241,10 @@ func (c *FloatingIPClient) Create(ctx context.Context, opts FloatingIPCreateOpts
 		Name:        opts.Name,
 	}
 	if opts.HomeLocation != nil {
-		reqBody.HomeLocation = String(opts.HomeLocation.Name)
+		reqBody.HomeLocation = Ptr(opts.HomeLocation.Name)
 	}
 	if opts.Server != nil {
-		reqBody.Server = Int(opts.Server.ID)
+		reqBody.Server = Ptr(opts.Server.ID)
 	}
 	if opts.Labels != nil {
 		reqBody.Labels = &opts.Labels
diff --git a/hcloud/floating_ip_test.go b/hcloud/floating_ip_test.go
index eb1709e..b3494a1 100644
--- a/hcloud/floating_ip_test.go
+++ b/hcloud/floating_ip_test.go
@@ -247,7 +247,7 @@ func TestFloatingIPClientCreate(t *testing.T) {
 
 	opts := FloatingIPCreateOpts{
 		Type:         FloatingIPTypeIPv4,
-		Description:  String("test"),
+		Description:  Ptr("test"),
 		HomeLocation: &Location{Name: "test"},
 		Server:       &Server{ID: 1},
 		Labels:       map[string]string{"key": "value"},
@@ -292,10 +292,10 @@ func TestFloatingIPClientCreateWithName(t *testing.T) {
 
 	opts := FloatingIPCreateOpts{
 		Type:         FloatingIPTypeIPv4,
-		Description:  String("test"),
+		Description:  Ptr("test"),
 		HomeLocation: &Location{Name: "test"},
 		Server:       &Server{ID: 1},
-		Name:         String("MyFloatingIP"),
+		Name:         Ptr("MyFloatingIP"),
 		Labels:       map[string]string{"key": "value"},
 	}
 
@@ -564,7 +564,7 @@ func TestFloatingIPClientChangeProtection(t *testing.T) {
 		})
 
 		opts := FloatingIPChangeProtectionOpts{
-			Delete: Bool(true),
+			Delete: Ptr(true),
 		}
 		action, _, err := env.Client.FloatingIP.ChangeProtection(ctx, floatingIP, opts)
 		if err != nil {
diff --git a/hcloud/hcloud.go b/hcloud/hcloud.go
index f850a35..ea08207 100644
--- a/hcloud/hcloud.go
+++ b/hcloud/hcloud.go
@@ -2,4 +2,4 @@
 package hcloud
 
 // Version is the library's version following Semantic Versioning.
-const Version = "1.35.2"
+const Version = "1.41.0" // x-release-please-version
diff --git a/hcloud/helper.go b/hcloud/helper.go
index e8e2642..1965609 100644
--- a/hcloud/helper.go
+++ b/hcloud/helper.go
@@ -2,17 +2,27 @@ package hcloud
 
 import "time"
 
+// Ptr returns a pointer to p.
+func Ptr[T any](p T) *T {
+	return &p
+}
+
 // String returns a pointer to the passed string s.
-func String(s string) *string { return &s }
+//
+// Deprecated: Use [Ptr] instead.
+func String(s string) *string { return Ptr(s) }
 
 // Int returns a pointer to the passed integer i.
-func Int(i int) *int { return &i }
+//
+// Deprecated: Use [Ptr] instead.
+func Int(i int) *int { return Ptr(i) }
 
 // Bool returns a pointer to the passed bool b.
-func Bool(b bool) *bool { return &b }
+//
+// Deprecated: Use [Ptr] instead.
+func Bool(b bool) *bool { return Ptr(b) }
 
 // Duration returns a pointer to the passed time.Duration d.
-func Duration(d time.Duration) *time.Duration { return &d }
-
-func intSlice(is []int) *[]int          { return &is }
-func stringSlice(ss []string) *[]string { return &ss }
+//
+// Deprecated: Use [Ptr] instead.
+func Duration(d time.Duration) *time.Duration { return Ptr(d) }
diff --git a/hcloud/image.go b/hcloud/image.go
index 0867aac..6a71898 100644
--- a/hcloud/image.go
+++ b/hcloud/image.go
@@ -222,7 +222,7 @@ func (c *ImageClient) Update(ctx context.Context, image *Image, opts ImageUpdate
 		Description: opts.Description,
 	}
 	if opts.Type != "" {
-		reqBody.Type = String(string(opts.Type))
+		reqBody.Type = Ptr(string(opts.Type))
 	}
 	if opts.Labels != nil {
 		reqBody.Labels = &opts.Labels
diff --git a/hcloud/image_test.go b/hcloud/image_test.go
index 6a339c0..28fd0cd 100644
--- a/hcloud/image_test.go
+++ b/hcloud/image_test.go
@@ -338,7 +338,7 @@ func TestImageClientUpdate(t *testing.T) {
 		})
 
 		opts := ImageUpdateOpts{
-			Description: String("test"),
+			Description: Ptr("test"),
 			Type:        ImageTypeSnapshot,
 		}
 		updatedImage, _, err := env.Client.Image.Update(ctx, image, opts)
@@ -417,7 +417,7 @@ func TestImageClientChangeProtection(t *testing.T) {
 		})
 
 		opts := ImageChangeProtectionOpts{
-			Delete: Bool(true),
+			Delete: Ptr(true),
 		}
 		action, _, err := env.Client.Image.ChangeProtection(ctx, image, opts)
 		if err != nil {
diff --git a/hcloud/internal/instrumentation/metrics.go b/hcloud/internal/instrumentation/metrics.go
index d8e9a2e..69a7165 100644
--- a/hcloud/internal/instrumentation/metrics.go
+++ b/hcloud/internal/instrumentation/metrics.go
@@ -16,7 +16,7 @@ type Instrumenter struct {
 	instrumentationRegistry *prometheus.Registry
 }
 
-// New creates a new Instrumenter. The subsystemIdentifier will be used as part of the metric names (e.g. hcloud_<identifier>_requests_total)
+// New creates a new Instrumenter. The subsystemIdentifier will be used as part of the metric names (e.g. hcloud_<identifier>_requests_total).
 func New(subsystemIdentifier string, instrumentationRegistry *prometheus.Registry) *Instrumenter {
 	return &Instrumenter{subsystemIdentifier: subsystemIdentifier, instrumentationRegistry: instrumentationRegistry}
 }
@@ -58,8 +58,10 @@ func (i *Instrumenter) InstrumentedRoundTripper() http.RoundTripper {
 
 // instrumentRoundTripperEndpoint implements a hcloud specific round tripper to count requests per API endpoint
 // numeric IDs are removed from the URI Path.
+//
 // Sample:
-// /volumes/1234/actions/attach --> /volumes/actions/attach
+//
+//	/volumes/1234/actions/attach --> /volumes/actions/attach
 func (i *Instrumenter) instrumentRoundTripperEndpoint(counter *prometheus.CounterVec, next http.RoundTripper) promhttp.RoundTripperFunc {
 	return func(r *http.Request) (*http.Response, error) {
 		resp, err := next.RoundTrip(r)
@@ -67,6 +69,7 @@ func (i *Instrumenter) instrumentRoundTripperEndpoint(counter *prometheus.Counte
 			statusCode := strconv.Itoa(resp.StatusCode)
 			counter.WithLabelValues(statusCode, strings.ToLower(resp.Request.Method), preparePathForLabel(resp.Request.URL.Path)).Inc()
 		}
+
 		return resp, err
 	}
 }
diff --git a/hcloud/iso.go b/hcloud/iso.go
index 3ec4a3d..ed2825b 100644
--- a/hcloud/iso.go
+++ b/hcloud/iso.go
@@ -19,7 +19,7 @@ type ISO struct {
 	Deprecated  time.Time
 }
 
-// IsDeprecated returns true if the ISO is deprecated
+// IsDeprecated returns true if the ISO is deprecated.
 func (iso *ISO) IsDeprecated() bool {
 	return !iso.Deprecated.IsZero()
 }
diff --git a/hcloud/load_balancer.go b/hcloud/load_balancer.go
index 96aeaf4..81e2e03 100644
--- a/hcloud/load_balancer.go
+++ b/hcloud/load_balancer.go
@@ -491,7 +491,6 @@ type LoadBalancerCreateResult struct {
 func (c *LoadBalancerClient) Create(ctx context.Context, opts LoadBalancerCreateOpts) (LoadBalancerCreateResult, *Response, error) {
 	reqBody := loadBalancerCreateOptsToSchema(opts)
 	reqBodyData, err := json.Marshal(reqBody)
-
 	if err != nil {
 		return LoadBalancerCreateResult{}, nil, err
 	}
@@ -865,7 +864,7 @@ func (c *LoadBalancerClient) AttachToNetwork(ctx context.Context, loadBalancer *
 		Network: opts.Network.ID,
 	}
 	if opts.IP != nil {
-		reqBody.IP = String(opts.IP.String())
+		reqBody.IP = Ptr(opts.IP.String())
 	}
 	reqBodyData, err := json.Marshal(reqBody)
 	if err != nil {
diff --git a/hcloud/load_balancer_test.go b/hcloud/load_balancer_test.go
index e414831..7d78341 100644
--- a/hcloud/load_balancer_test.go
+++ b/hcloud/load_balancer_test.go
@@ -179,7 +179,7 @@ func TestLoadBalancerCreate(t *testing.T) {
 			Algorithm: &schema.LoadBalancerCreateRequestAlgorithm{
 				Type: "round_robin",
 			},
-			Location: String("fsn1"),
+			Location: Ptr("fsn1"),
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
 			t.Log(cmp.Diff(expectedReqBody, reqBody))
@@ -246,7 +246,7 @@ func TestLoadBalancerClientUpdate(t *testing.T) {
 			t.Fatal(err)
 		}
 		expectedReqBody := schema.LoadBalancerUpdateRequest{
-			Name: String("test"),
+			Name: Ptr("test"),
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
 			t.Log(cmp.Diff(expectedReqBody, reqBody))
@@ -289,7 +289,7 @@ func TestLoadBalancerClientChangeProtection(t *testing.T) {
 			t.Fatal(err)
 		}
 		expectedReqBody := schema.LoadBalancerActionChangeProtectionRequest{
-			Delete: Bool(true),
+			Delete: Ptr(true),
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
 			t.Log(cmp.Diff(expectedReqBody, reqBody))
@@ -308,7 +308,7 @@ func TestLoadBalancerClientChangeProtection(t *testing.T) {
 	)
 
 	opts := LoadBalancerChangeProtectionOpts{
-		Delete: Bool(true),
+		Delete: Ptr(true),
 	}
 	action, _, err := env.Client.LoadBalancer.ChangeProtection(ctx, loadBalancer, opts)
 	if err != nil {
@@ -336,7 +336,7 @@ func TestLoadBalancerClientAddServerTarget(t *testing.T) {
 			Server: &schema.LoadBalancerActionAddTargetRequestServer{
 				ID: 1,
 			},
-			UsePrivateIP: Bool(true),
+			UsePrivateIP: Ptr(true),
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
 			t.Log(cmp.Diff(expectedReqBody, reqBody))
@@ -357,7 +357,7 @@ func TestLoadBalancerClientAddServerTarget(t *testing.T) {
 
 	opts := LoadBalancerAddServerTargetOpts{
 		Server:       server,
-		UsePrivateIP: Bool(true),
+		UsePrivateIP: Ptr(true),
 	}
 	action, _, err := env.Client.LoadBalancer.AddServerTarget(ctx, loadBalancer, opts)
 	if err != nil {
@@ -426,23 +426,23 @@ func TestLoadBalancerAddService(t *testing.T) {
 		}
 		expectedReqBody := schema.LoadBalancerActionAddServiceRequest{
 			Protocol:        string(LoadBalancerServiceProtocolHTTP),
-			ListenPort:      Int(4711),
-			DestinationPort: Int(80),
+			ListenPort:      Ptr(4711),
+			DestinationPort: Ptr(80),
 			HTTP: &schema.LoadBalancerActionAddServiceRequestHTTP{
-				CookieName:     String("HCLBSTICKY"),
-				CookieLifetime: Int(5 * 60),
-				RedirectHTTP:   Bool(false),
-				StickySessions: Bool(true),
+				CookieName:     Ptr("HCLBSTICKY"),
+				CookieLifetime: Ptr(5 * 60),
+				RedirectHTTP:   Ptr(false),
+				StickySessions: Ptr(true),
 			},
 			HealthCheck: &schema.LoadBalancerActionAddServiceRequestHealthCheck{
 				Protocol: "http",
-				Port:     Int(4711),
-				Interval: Int(15),
-				Timeout:  Int(10),
-				Retries:  Int(3),
+				Port:     Ptr(4711),
+				Interval: Ptr(15),
+				Timeout:  Ptr(10),
+				Retries:  Ptr(3),
 				HTTP: &schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP{
-					Domain: String("example.com"),
-					Path:   String("/"),
+					Domain: Ptr("example.com"),
+					Path:   Ptr("/"),
 				},
 			},
 		}
@@ -464,23 +464,23 @@ func TestLoadBalancerAddService(t *testing.T) {
 
 	opts := LoadBalancerAddServiceOpts{
 		Protocol:        LoadBalancerServiceProtocolHTTP,
-		ListenPort:      Int(4711),
-		DestinationPort: Int(80),
+		ListenPort:      Ptr(4711),
+		DestinationPort: Ptr(80),
 		HTTP: &LoadBalancerAddServiceOptsHTTP{
-			CookieName:     String("HCLBSTICKY"),
-			CookieLifetime: Duration(5 * time.Minute),
-			RedirectHTTP:   Bool(false),
-			StickySessions: Bool(true),
+			CookieName:     Ptr("HCLBSTICKY"),
+			CookieLifetime: Ptr(5 * time.Minute),
+			RedirectHTTP:   Ptr(false),
+			StickySessions: Ptr(true),
 		},
 		HealthCheck: &LoadBalancerAddServiceOptsHealthCheck{
 			Protocol: "http",
-			Port:     Int(4711),
-			Interval: Duration(15 * time.Second),
-			Timeout:  Duration(10 * time.Second),
-			Retries:  Int(3),
+			Port:     Ptr(4711),
+			Interval: Ptr(15 * time.Second),
+			Timeout:  Ptr(10 * time.Second),
+			Retries:  Ptr(3),
 			HTTP: &LoadBalancerAddServiceOptsHealthCheckHTTP{
-				Domain: String("example.com"),
-				Path:   String("/"),
+				Domain: Ptr("example.com"),
+				Path:   Ptr("/"),
 			},
 		},
 	}
@@ -506,24 +506,24 @@ func TestLoadBalancerUpdateService(t *testing.T) {
 			t.Fatal(err)
 		}
 		expectedReqBody := schema.LoadBalancerActionUpdateServiceRequest{
-			Protocol:        String(string(LoadBalancerServiceProtocolHTTP)),
+			Protocol:        Ptr(string(LoadBalancerServiceProtocolHTTP)),
 			ListenPort:      4711,
-			DestinationPort: Int(80),
+			DestinationPort: Ptr(80),
 			HTTP: &schema.LoadBalancerActionUpdateServiceRequestHTTP{
-				CookieName:     String("HCLBSTICKY"),
-				CookieLifetime: Int(5 * 60),
-				RedirectHTTP:   Bool(false),
-				StickySessions: Bool(true),
+				CookieName:     Ptr("HCLBSTICKY"),
+				CookieLifetime: Ptr(5 * 60),
+				RedirectHTTP:   Ptr(false),
+				StickySessions: Ptr(true),
 			},
 			HealthCheck: &schema.LoadBalancerActionUpdateServiceRequestHealthCheck{
-				Protocol: String(string(LoadBalancerServiceProtocolHTTP)),
-				Port:     Int(4711),
-				Interval: Int(15),
-				Timeout:  Int(10),
-				Retries:  Int(3),
+				Protocol: Ptr(string(LoadBalancerServiceProtocolHTTP)),
+				Port:     Ptr(4711),
+				Interval: Ptr(15),
+				Timeout:  Ptr(10),
+				Retries:  Ptr(3),
 				HTTP: &schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP{
-					Domain: String("example.com"),
-					Path:   String("/"),
+					Domain: Ptr("example.com"),
+					Path:   Ptr("/"),
 				},
 			},
 		}
@@ -545,22 +545,22 @@ func TestLoadBalancerUpdateService(t *testing.T) {
 
 	opts := LoadBalancerUpdateServiceOpts{
 		Protocol:        LoadBalancerServiceProtocolHTTP,
-		DestinationPort: Int(80),
+		DestinationPort: Ptr(80),
 		HTTP: &LoadBalancerUpdateServiceOptsHTTP{
-			CookieName:     String("HCLBSTICKY"),
-			CookieLifetime: Duration(5 * time.Minute),
-			RedirectHTTP:   Bool(false),
-			StickySessions: Bool(true),
+			CookieName:     Ptr("HCLBSTICKY"),
+			CookieLifetime: Ptr(5 * time.Minute),
+			RedirectHTTP:   Ptr(false),
+			StickySessions: Ptr(true),
 		},
 		HealthCheck: &LoadBalancerUpdateServiceOptsHealthCheck{
 			Protocol: LoadBalancerServiceProtocolHTTP,
-			Port:     Int(4711),
-			Interval: Duration(15 * time.Second),
-			Timeout:  Duration(10 * time.Second),
-			Retries:  Int(3),
+			Port:     Ptr(4711),
+			Interval: Ptr(15 * time.Second),
+			Timeout:  Ptr(10 * time.Second),
+			Retries:  Ptr(3),
 			HTTP: &LoadBalancerUpdateServiceOptsHealthCheckHTTP{
-				Domain: String("example.com"),
-				Path:   String("/"),
+				Domain: Ptr("example.com"),
+				Path:   Ptr("/"),
 			},
 		},
 	}
@@ -670,7 +670,7 @@ func TestLoadBalancerClientAttachToNetwork(t *testing.T) {
 		}
 		expectedReqBody := schema.LoadBalancerActionAttachToNetworkRequest{
 			Network: 1,
-			IP:      String("10.0.1.1"),
+			IP:      Ptr("10.0.1.1"),
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
 			t.Log(cmp.Diff(expectedReqBody, reqBody))
@@ -898,7 +898,7 @@ func TestLoadBalancerClientAddLabelSelectorTarget(t *testing.T) {
 	ctx := context.Background()
 	action, _, err := env.Client.LoadBalancer.AddLabelSelectorTarget(ctx, &LoadBalancer{ID: 1}, LoadBalancerAddLabelSelectorTargetOpts{
 		Selector:     "key=value",
-		UsePrivateIP: Bool(false),
+		UsePrivateIP: Ptr(false),
 	})
 	if err != nil {
 		t.Fatal(err)
diff --git a/hcloud/metadata/client.go b/hcloud/metadata/client.go
index 7bfa18e..4c173d7 100644
--- a/hcloud/metadata/client.go
+++ b/hcloud/metadata/client.go
@@ -8,8 +8,9 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/hetznercloud/hcloud-go/hcloud/internal/instrumentation"
 	"github.com/prometheus/client_golang/prometheus"
+
+	"github.com/hetznercloud/hcloud-go/hcloud/internal/instrumentation"
 )
 
 const Endpoint = "http://169.254.169.254/hetzner/v1/metadata"
@@ -85,7 +86,7 @@ func (c *Client) get(path string) (string, error) {
 }
 
 // IsHcloudServer checks if the currently called server is a hcloud server by calling a metadata endpoint
-// if the endpoint answers with a non-empty value this method returns true, otherwise false
+// if the endpoint answers with a non-empty value this method returns true, otherwise false.
 func (c *Client) IsHcloudServer() bool {
 	hostname, err := c.Hostname()
 	if err != nil {
@@ -97,12 +98,12 @@ func (c *Client) IsHcloudServer() bool {
 	return false
 }
 
-// Hostname returns the hostname of the server that did the request to the Metadata server
+// Hostname returns the hostname of the server that did the request to the Metadata server.
 func (c *Client) Hostname() (string, error) {
 	return c.get("/hostname")
 }
 
-// InstanceID returns the ID of the server that did the request to the Metadata server
+// InstanceID returns the ID of the server that did the request to the Metadata server.
 func (c *Client) InstanceID() (int, error) {
 	resp, err := c.get("/instance-id")
 	if err != nil {
@@ -111,7 +112,7 @@ func (c *Client) InstanceID() (int, error) {
 	return strconv.Atoi(resp)
 }
 
-// PublicIPv4 returns the Public IPv4 of the server that did the request to the Metadata server
+// PublicIPv4 returns the Public IPv4 of the server that did the request to the Metadata server.
 func (c *Client) PublicIPv4() (net.IP, error) {
 	resp, err := c.get("/public-ipv4")
 	if err != nil {
@@ -120,18 +121,18 @@ func (c *Client) PublicIPv4() (net.IP, error) {
 	return net.ParseIP(resp), nil
 }
 
-// Region returns the Network Zone of the server that did the request to the Metadata server
+// Region returns the Network Zone of the server that did the request to the Metadata server.
 func (c *Client) Region() (string, error) {
 	return c.get("/region")
 }
 
-// AvailabilityZone returns the datacenter of the server that did the request to the Metadata server
+// AvailabilityZone returns the datacenter of the server that did the request to the Metadata server.
 func (c *Client) AvailabilityZone() (string, error) {
 	return c.get("/availability-zone")
 }
 
-// PrivateNetworks returns details about the private networks the server is attached to
-// Returns YAML (unparsed)
+// PrivateNetworks returns details about the private networks the server is attached to.
+// Returns YAML (unparsed).
 func (c *Client) PrivateNetworks() (string, error) {
 	return c.get("/private-networks")
 }
diff --git a/hcloud/network.go b/hcloud/network.go
index e3bf6de..5a19681 100644
--- a/hcloud/network.go
+++ b/hcloud/network.go
@@ -21,6 +21,7 @@ type NetworkZone string
 const (
 	NetworkZoneEUCentral NetworkZone = "eu-central"
 	NetworkZoneUSEast    NetworkZone = "us-east"
+	NetworkZoneUSWest    NetworkZone = "us-west"
 )
 
 // NetworkSubnetType specifies a type of a subnet.
diff --git a/hcloud/network_test.go b/hcloud/network_test.go
index 5b0855b..d5f5d00 100644
--- a/hcloud/network_test.go
+++ b/hcloud/network_test.go
@@ -622,7 +622,7 @@ func TestNetworkClientChangeProtection(t *testing.T) {
 		})
 
 		opts := NetworkChangeProtectionOpts{
-			Delete: Bool(true),
+			Delete: Ptr(true),
 		}
 		action, _, err := env.Client.Network.ChangeProtection(ctx, network, opts)
 		if err != nil {
diff --git a/hcloud/placement_group.go b/hcloud/placement_group.go
index 5056a11..07fedad 100644
--- a/hcloud/placement_group.go
+++ b/hcloud/placement_group.go
@@ -23,11 +23,11 @@ type PlacementGroup struct {
 	Type    PlacementGroupType
 }
 
-// PlacementGroupType specifies the type of a Placement Group
+// PlacementGroupType specifies the type of a Placement Group.
 type PlacementGroupType string
 
 const (
-	// PlacementGroupTypeSpread spreads all servers in the group on different vhosts
+	// PlacementGroupTypeSpread spreads all servers in the group on different vhosts.
 	PlacementGroupTypeSpread PlacementGroupType = "spread"
 )
 
@@ -158,7 +158,7 @@ type PlacementGroupCreateOpts struct {
 	Type   PlacementGroupType
 }
 
-// Validate checks if options are valid
+// Validate checks if options are valid.
 func (o PlacementGroupCreateOpts) Validate() error {
 	if o.Name == "" {
 		return errors.New("missing name")
@@ -172,7 +172,7 @@ type PlacementGroupCreateResult struct {
 	Action         *Action
 }
 
-// Create creates a new PlacementGroup
+// Create creates a new PlacementGroup.
 func (c *PlacementGroupClient) Create(ctx context.Context, opts PlacementGroupCreateOpts) (PlacementGroupCreateResult, *Response, error) {
 	if err := opts.Validate(); err != nil {
 		return PlacementGroupCreateResult{}, nil, err
diff --git a/hcloud/placement_group_test.go b/hcloud/placement_group_test.go
index 334f591..fd2caed 100644
--- a/hcloud/placement_group_test.go
+++ b/hcloud/placement_group_test.go
@@ -8,6 +8,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
diff --git a/hcloud/pricing.go b/hcloud/pricing.go
index 67be21f..836f391 100644
--- a/hcloud/pricing.go
+++ b/hcloud/pricing.go
@@ -56,12 +56,13 @@ type FloatingIPTypePricing struct {
 // PrimaryIPTypePricing defines the schema of pricing information for a primary IP
 // type at a datacenter.
 type PrimaryIPTypePricing struct {
-	Datacenter string
+	Datacenter string // Deprecated: the API does not return pricing for the individual DCs anymore
+	Location   string
 	Hourly     PrimaryIPPrice
 	Monthly    PrimaryIPPrice
 }
 
-// PrimaryIPTypePricing provides pricing information for PrimaryIPs
+// PrimaryIPTypePricing provides pricing information for PrimaryIPs.
 type PrimaryIPPricing struct {
 	Type     string
 	Pricings []PrimaryIPTypePricing
diff --git a/hcloud/primary_ip.go b/hcloud/primary_ip.go
index c534c89..e328b9b 100644
--- a/hcloud/primary_ip.go
+++ b/hcloud/primary_ip.go
@@ -13,7 +13,7 @@ import (
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
-// PrimaryIP defines a Primary IP
+// PrimaryIP defines a Primary IP.
 type PrimaryIP struct {
 	ID           int
 	IP           net.IP
@@ -90,12 +90,6 @@ type PrimaryIPUpdateOpts struct {
 	Name       string             `json:"name,omitempty"`
 }
 
-// PrimaryIPUpdateResult defines the response
-// when updating a Primary IP.
-type PrimaryIPUpdateResult struct {
-	PrimaryIP PrimaryIP `json:"primary_ip"`
-}
-
 // PrimaryIPAssignOpts defines the request to
 // assign a Primary IP to an assignee (usually a server).
 type PrimaryIPAssignOpts struct {
@@ -111,7 +105,7 @@ type PrimaryIPAssignResult struct {
 }
 
 // PrimaryIPChangeDNSPtrOpts defines the request to
-// change a DNS PTR entry from a Primary IP
+// change a DNS PTR entry from a Primary IP.
 type PrimaryIPChangeDNSPtrOpts struct {
 	ID     int
 	DNSPtr string `json:"dns_ptr"`
@@ -125,19 +119,19 @@ type PrimaryIPChangeDNSPtrResult struct {
 }
 
 // PrimaryIPChangeProtectionOpts defines the request to
-// change protection configuration of a Primary IP
+// change protection configuration of a Primary IP.
 type PrimaryIPChangeProtectionOpts struct {
 	ID     int
 	Delete bool `json:"delete"`
 }
 
 // PrimaryIPChangeProtectionResult defines the response
-// when changing a protection of a PrimaryIP
+// when changing a protection of a PrimaryIP.
 type PrimaryIPChangeProtectionResult struct {
 	Action schema.Action `json:"action"`
 }
 
-// PrimaryIPClient is a client for the Primary IP API
+// PrimaryIPClient is a client for the Primary IP API.
 type PrimaryIPClient struct {
 	client *Client
 }
@@ -240,10 +234,12 @@ func (c *PrimaryIPClient) List(ctx context.Context, opts PrimaryIPListOpts) ([]*
 
 // All returns all Primary IPs.
 func (c *PrimaryIPClient) All(ctx context.Context) ([]*PrimaryIP, error) {
-	allPrimaryIPs := []*PrimaryIP{}
+	return c.AllWithOpts(ctx, PrimaryIPListOpts{ListOpts: ListOpts{PerPage: 50}})
+}
 
-	opts := PrimaryIPListOpts{}
-	opts.PerPage = 50
+// AllWithOpts returns all Primary IPs for the given options.
+func (c *PrimaryIPClient) AllWithOpts(ctx context.Context, opts PrimaryIPListOpts) ([]*PrimaryIP, error) {
+	var allPrimaryIPs []*PrimaryIP
 
 	err := c.client.all(func(page int) (*Response, error) {
 		opts.Page = page
@@ -311,15 +307,15 @@ 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
+// Assign a Primary IP to a resource.
 func (c *PrimaryIPClient) Assign(ctx context.Context, opts PrimaryIPAssignOpts) (*Action, *Response, error) {
 	reqBodyData, err := json.Marshal(opts)
 	if err != nil {
@@ -340,7 +336,7 @@ func (c *PrimaryIPClient) Assign(ctx context.Context, opts PrimaryIPAssignOpts)
 	return ActionFromSchema(respBody.Action), resp, nil
 }
 
-// Unassign a Primary IP from a resource
+// Unassign a Primary IP from a resource.
 func (c *PrimaryIPClient) Unassign(ctx context.Context, id int) (*Action, *Response, error) {
 	path := fmt.Sprintf("/primary_ips/%d/actions/unassign", id)
 	req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader([]byte{}))
@@ -356,7 +352,7 @@ func (c *PrimaryIPClient) Unassign(ctx context.Context, id int) (*Action, *Respo
 	return ActionFromSchema(respBody.Action), resp, nil
 }
 
-// ChangeDNSPtr Change the reverse DNS from a Primary IP
+// ChangeDNSPtr Change the reverse DNS from a Primary IP.
 func (c *PrimaryIPClient) ChangeDNSPtr(ctx context.Context, opts PrimaryIPChangeDNSPtrOpts) (*Action, *Response, error) {
 	reqBodyData, err := json.Marshal(opts)
 	if err != nil {
diff --git a/hcloud/primary_ip_test.go b/hcloud/primary_ip_test.go
index 6c517ee..d368b71 100644
--- a/hcloud/primary_ip_test.go
+++ b/hcloud/primary_ip_test.go
@@ -3,12 +3,14 @@ package hcloud
 import (
 	"context"
 	"encoding/json"
+	"net"
 	"net/http"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 	"github.com/stretchr/testify/assert"
+
+	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
 func TestPrimaryIPClient(t *testing.T) {
@@ -333,8 +335,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"},
 			})
 		})
 
@@ -347,11 +349,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()
diff --git a/hcloud/rdns.go b/hcloud/rdns.go
index 70d31f9..891ea2b 100644
--- a/hcloud/rdns.go
+++ b/hcloud/rdns.go
@@ -7,7 +7,7 @@ import (
 )
 
 // RDNSSupporter defines functions to change and lookup reverse dns entries.
-// currently implemented by Server, FloatingIP and LoadBalancer
+// currently implemented by Server, FloatingIP and LoadBalancer.
 type RDNSSupporter interface {
 	// changeDNSPtr changes or resets the reverse DNS pointer for a IP address.
 	// Pass a nil ptr to reset the reverse DNS pointer to its default value.
diff --git a/hcloud/schema.go b/hcloud/schema.go
index 633a568..091426b 100644
--- a/hcloud/schema.go
+++ b/hcloud/schema.go
@@ -721,7 +721,7 @@ func PricingFromSchema(s schema.Pricing) Pricing {
 		var pricings []PrimaryIPTypePricing
 		for _, price := range primaryIPType.Prices {
 			p := PrimaryIPTypePricing{
-				Datacenter: price.Datacenter,
+				Location: price.Location,
 				Monthly: PrimaryIPPrice{
 					Net:   price.PriceMonthly.Net,
 					Gross: price.PriceMonthly.Gross,
@@ -881,19 +881,19 @@ func loadBalancerCreateOptsToSchema(opts LoadBalancerCreateOpts) schema.LoadBala
 	}
 	if opts.Location != nil {
 		if opts.Location.ID != 0 {
-			req.Location = String(strconv.Itoa(opts.Location.ID))
+			req.Location = Ptr(strconv.Itoa(opts.Location.ID))
 		} else {
-			req.Location = String(opts.Location.Name)
+			req.Location = Ptr(opts.Location.Name)
 		}
 	}
 	if opts.NetworkZone != "" {
-		req.NetworkZone = String(string(opts.NetworkZone))
+		req.NetworkZone = Ptr(string(opts.NetworkZone))
 	}
 	if opts.Labels != nil {
 		req.Labels = &opts.Labels
 	}
 	if opts.Network != nil {
-		req.Network = Int(opts.Network.ID)
+		req.Network = Ptr(opts.Network.ID)
 	}
 	for _, target := range opts.Targets {
 		schemaTarget := schema.LoadBalancerCreateRequestTarget{
@@ -927,7 +927,7 @@ func loadBalancerCreateOptsToSchema(opts LoadBalancerCreateOpts) schema.LoadBala
 			}
 			if service.HTTP.CookieLifetime != nil {
 				if sec := service.HTTP.CookieLifetime.Seconds(); sec != 0 {
-					schemaService.HTTP.CookieLifetime = Int(int(sec))
+					schemaService.HTTP.CookieLifetime = Ptr(int(sec))
 				}
 			}
 			if service.HTTP.Certificates != nil {
@@ -945,10 +945,10 @@ func loadBalancerCreateOptsToSchema(opts LoadBalancerCreateOpts) schema.LoadBala
 				Retries:  service.HealthCheck.Retries,
 			}
 			if service.HealthCheck.Interval != nil {
-				schemaHealthCheck.Interval = Int(int(service.HealthCheck.Interval.Seconds()))
+				schemaHealthCheck.Interval = Ptr(int(service.HealthCheck.Interval.Seconds()))
 			}
 			if service.HealthCheck.Timeout != nil {
-				schemaHealthCheck.Timeout = Int(int(service.HealthCheck.Timeout.Seconds()))
+				schemaHealthCheck.Timeout = Ptr(int(service.HealthCheck.Timeout.Seconds()))
 			}
 			if service.HealthCheck.HTTP != nil {
 				schemaHealthCheckHTTP := &schema.LoadBalancerCreateRequestServiceHealthCheckHTTP{
@@ -983,7 +983,7 @@ func loadBalancerAddServiceOptsToSchema(opts LoadBalancerAddServiceOpts) schema.
 			StickySessions: opts.HTTP.StickySessions,
 		}
 		if opts.HTTP.CookieLifetime != nil {
-			req.HTTP.CookieLifetime = Int(int(opts.HTTP.CookieLifetime.Seconds()))
+			req.HTTP.CookieLifetime = Ptr(int(opts.HTTP.CookieLifetime.Seconds()))
 		}
 		if opts.HTTP.Certificates != nil {
 			certificates := []int{}
@@ -1000,10 +1000,10 @@ func loadBalancerAddServiceOptsToSchema(opts LoadBalancerAddServiceOpts) schema.
 			Retries:  opts.HealthCheck.Retries,
 		}
 		if opts.HealthCheck.Interval != nil {
-			req.HealthCheck.Interval = Int(int(opts.HealthCheck.Interval.Seconds()))
+			req.HealthCheck.Interval = Ptr(int(opts.HealthCheck.Interval.Seconds()))
 		}
 		if opts.HealthCheck.Timeout != nil {
-			req.HealthCheck.Timeout = Int(int(opts.HealthCheck.Timeout.Seconds()))
+			req.HealthCheck.Timeout = Ptr(int(opts.HealthCheck.Timeout.Seconds()))
 		}
 		if opts.HealthCheck.HTTP != nil {
 			req.HealthCheck.HTTP = &schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP{
@@ -1026,7 +1026,7 @@ func loadBalancerUpdateServiceOptsToSchema(opts LoadBalancerUpdateServiceOpts) s
 		Proxyprotocol:   opts.Proxyprotocol,
 	}
 	if opts.Protocol != "" {
-		req.Protocol = String(string(opts.Protocol))
+		req.Protocol = Ptr(string(opts.Protocol))
 	}
 	if opts.HTTP != nil {
 		req.HTTP = &schema.LoadBalancerActionUpdateServiceRequestHTTP{
@@ -1035,7 +1035,7 @@ func loadBalancerUpdateServiceOptsToSchema(opts LoadBalancerUpdateServiceOpts) s
 			StickySessions: opts.HTTP.StickySessions,
 		}
 		if opts.HTTP.CookieLifetime != nil {
-			req.HTTP.CookieLifetime = Int(int(opts.HTTP.CookieLifetime.Seconds()))
+			req.HTTP.CookieLifetime = Ptr(int(opts.HTTP.CookieLifetime.Seconds()))
 		}
 		if opts.HTTP.Certificates != nil {
 			certificates := []int{}
@@ -1051,13 +1051,13 @@ func loadBalancerUpdateServiceOptsToSchema(opts LoadBalancerUpdateServiceOpts) s
 			Retries: opts.HealthCheck.Retries,
 		}
 		if opts.HealthCheck.Interval != nil {
-			req.HealthCheck.Interval = Int(int(opts.HealthCheck.Interval.Seconds()))
+			req.HealthCheck.Interval = Ptr(int(opts.HealthCheck.Interval.Seconds()))
 		}
 		if opts.HealthCheck.Timeout != nil {
-			req.HealthCheck.Timeout = Int(int(opts.HealthCheck.Timeout.Seconds()))
+			req.HealthCheck.Timeout = Ptr(int(opts.HealthCheck.Timeout.Seconds()))
 		}
 		if opts.HealthCheck.Protocol != "" {
-			req.HealthCheck.Protocol = String(string(opts.HealthCheck.Protocol))
+			req.HealthCheck.Protocol = Ptr(string(opts.HealthCheck.Protocol))
 		}
 		if opts.HealthCheck.HTTP != nil {
 			req.HealthCheck.HTTP = &schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP{
diff --git a/hcloud/schema/pricing.go b/hcloud/schema/pricing.go
index b97a2f8..0c06c73 100644
--- a/hcloud/schema/pricing.go
+++ b/hcloud/schema/pricing.go
@@ -94,15 +94,16 @@ type PricingGetResponse struct {
 	Pricing Pricing `json:"pricing"`
 }
 
-// PricingPrimaryIPTypePrice defines the schema of pricing information for a primary IP
+// PricingPrimaryIPTypePrice defines the schema of pricing information for a primary IP.
 // type at a datacenter.
 type PricingPrimaryIPTypePrice struct {
-	Datacenter   string `json:"datacenter"`
+	Datacenter   string `json:"datacenter"` // Deprecated: the API does not return pricing for the individual DCs anymore
+	Location     string `json:"location"`
 	PriceHourly  Price  `json:"price_hourly"`
 	PriceMonthly Price  `json:"price_monthly"`
 }
 
-// PricingPrimaryIP define the schema of pricing information for a primary IP at a datacenter
+// PricingPrimaryIP define the schema of pricing information for a primary IP at a datacenter.
 type PricingPrimaryIP struct {
 	Type   string                      `json:"type"`
 	Prices []PricingPrimaryIPTypePrice `json:"prices"`
diff --git a/hcloud/schema/primary_ip.go b/hcloud/schema/primary_ip.go
index b21e28b..d232a73 100644
--- a/hcloud/schema/primary_ip.go
+++ b/hcloud/schema/primary_ip.go
@@ -2,7 +2,7 @@ package schema
 
 import "time"
 
-// PrimaryIP defines a Primary IP
+// PrimaryIP defines a Primary IP.
 type PrimaryIP struct {
 	ID           int                 `json:"id"`
 	IP           string              `json:"ip"`
@@ -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"`
+}
diff --git a/hcloud/schema/server.go b/hcloud/schema/server.go
index 616b2eb..4786b1f 100644
--- a/hcloud/schema/server.go
+++ b/hcloud/schema/server.go
@@ -136,6 +136,12 @@ type ServerCreateResponse struct {
 	NextActions  []Action `json:"next_actions"`
 }
 
+// ServerDeleteResponse defines the schema of the response when
+// deleting a server.
+type ServerDeleteResponse struct {
+	Action Action `json:"action"`
+}
+
 // ServerUpdateRequest defines the schema of the request to update a server.
 type ServerUpdateRequest struct {
 	Name   string             `json:"name,omitempty"`
@@ -256,7 +262,8 @@ type ServerActionRebuildRequest struct {
 // ServerActionRebuildResponse defines the schema of the response when
 // creating a rebuild server action.
 type ServerActionRebuildResponse struct {
-	Action Action `json:"action"`
+	Action       Action  `json:"action"`
+	RootPassword *string `json:"root_password"`
 }
 
 // ServerActionAttachISORequest defines the schema for the request to
diff --git a/hcloud/schema_test.go b/hcloud/schema_test.go
index 9301d78..fd0a364 100644
--- a/hcloud/schema_test.go
+++ b/hcloud/schema_test.go
@@ -2044,7 +2044,7 @@ func TestPricingFromSchema(t *testing.T) {
 			{
 				"prices": [
 				{
-					"datacenter": "fsn1-dc8",
+					"location": "fsn1",
 					"price_hourly": {
 					"gross": "1.1900000000000000",
 					"net": "1.0000000000"
@@ -2185,8 +2185,8 @@ func TestPricingFromSchema(t *testing.T) {
 		if len(ip.Pricings) != 1 {
 			t.Errorf("unexpected number of prices: %d", len(ip.Pricings))
 		} else {
-			if ip.Pricings[0].Datacenter != "fsn1-dc8" {
-				t.Errorf("unexpected Datacenter: %v", ip.Pricings[0].Datacenter)
+			if ip.Pricings[0].Location != "fsn1" {
+				t.Errorf("unexpected Location: %v", ip.Pricings[0].Location)
 			}
 			if ip.Pricings[0].Monthly.Net != "1.0000000000" {
 				t.Errorf("unexpected Monthly.Net: %v", ip.Pricings[0].Monthly.Net)
@@ -2346,7 +2346,7 @@ func TestLoadBalancerCreateOptsToSchema(t *testing.T) {
 				Algorithm: &schema.LoadBalancerCreateRequestAlgorithm{
 					Type: string(LoadBalancerAlgorithmTypeRoundRobin),
 				},
-				NetworkZone: String(string(NetworkZoneEUCentral)),
+				NetworkZone: Ptr(string(NetworkZoneEUCentral)),
 			},
 		},
 		"all set": {
@@ -2356,32 +2356,32 @@ func TestLoadBalancerCreateOptsToSchema(t *testing.T) {
 				Algorithm:        &LoadBalancerAlgorithm{Type: LoadBalancerAlgorithmTypeRoundRobin},
 				NetworkZone:      NetworkZoneEUCentral,
 				Labels:           map[string]string{"foo": "bar"},
-				PublicInterface:  Bool(true),
+				PublicInterface:  Ptr(true),
 				Network:          &Network{ID: 3},
 				Services: []LoadBalancerCreateOptsService{
 					{
 						Protocol:        LoadBalancerServiceProtocolHTTP,
-						DestinationPort: Int(80),
-						Proxyprotocol:   Bool(true),
+						DestinationPort: Ptr(80),
+						Proxyprotocol:   Ptr(true),
 						HTTP: &LoadBalancerCreateOptsServiceHTTP{
-							CookieName:     String("keks"),
-							CookieLifetime: Duration(5 * time.Minute),
-							RedirectHTTP:   Bool(true),
-							StickySessions: Bool(true),
+							CookieName:     Ptr("keks"),
+							CookieLifetime: Ptr(5 * time.Minute),
+							RedirectHTTP:   Ptr(true),
+							StickySessions: Ptr(true),
 							Certificates:   []*Certificate{{ID: 1}, {ID: 2}},
 						},
 						HealthCheck: &LoadBalancerCreateOptsServiceHealthCheck{
 							Protocol: LoadBalancerServiceProtocolHTTP,
-							Port:     Int(80),
-							Interval: Duration(5 * time.Second),
-							Timeout:  Duration(1 * time.Second),
-							Retries:  Int(3),
+							Port:     Ptr(80),
+							Interval: Ptr(5 * time.Second),
+							Timeout:  Ptr(1 * time.Second),
+							Retries:  Ptr(3),
 							HTTP: &LoadBalancerCreateOptsServiceHealthCheckHTTP{
-								Domain:      String("example.com"),
-								Path:        String("/health"),
-								Response:    String("ok"),
+								Domain:      Ptr("example.com"),
+								Path:        Ptr("/health"),
+								Response:    Ptr("ok"),
 								StatusCodes: []string{"2??", "3??"},
-								TLS:         Bool(true),
+								TLS:         Ptr(true),
 							},
 						},
 					},
@@ -2405,37 +2405,37 @@ func TestLoadBalancerCreateOptsToSchema(t *testing.T) {
 				Algorithm: &schema.LoadBalancerCreateRequestAlgorithm{
 					Type: string(LoadBalancerAlgorithmTypeRoundRobin),
 				},
-				NetworkZone: String(string(NetworkZoneEUCentral)),
+				NetworkZone: Ptr(string(NetworkZoneEUCentral)),
 				Labels: func() *map[string]string {
 					labels := map[string]string{"foo": "bar"}
 					return &labels
 				}(),
-				PublicInterface: Bool(true),
-				Network:         Int(3),
+				PublicInterface: Ptr(true),
+				Network:         Ptr(3),
 				Services: []schema.LoadBalancerCreateRequestService{
 					{
 						Protocol:        string(LoadBalancerServiceProtocolHTTP),
-						DestinationPort: Int(80),
-						Proxyprotocol:   Bool(true),
+						DestinationPort: Ptr(80),
+						Proxyprotocol:   Ptr(true),
 						HTTP: &schema.LoadBalancerCreateRequestServiceHTTP{
-							CookieName:     String("keks"),
-							CookieLifetime: Int(5 * 60),
-							RedirectHTTP:   Bool(true),
-							StickySessions: Bool(true),
-							Certificates:   intSlice([]int{1, 2}),
+							CookieName:     Ptr("keks"),
+							CookieLifetime: Ptr(5 * 60),
+							RedirectHTTP:   Ptr(true),
+							StickySessions: Ptr(true),
+							Certificates:   Ptr([]int{1, 2}),
 						},
 						HealthCheck: &schema.LoadBalancerCreateRequestServiceHealthCheck{
 							Protocol: string(LoadBalancerServiceProtocolHTTP),
-							Port:     Int(80),
-							Interval: Int(5),
-							Timeout:  Int(1),
-							Retries:  Int(3),
+							Port:     Ptr(80),
+							Interval: Ptr(5),
+							Timeout:  Ptr(1),
+							Retries:  Ptr(3),
 							HTTP: &schema.LoadBalancerCreateRequestServiceHealthCheckHTTP{
-								Domain:      String("example.com"),
-								Path:        String("/health"),
-								Response:    String("ok"),
-								StatusCodes: stringSlice([]string{"2??", "3??"}),
-								TLS:         Bool(true),
+								Domain:      Ptr("example.com"),
+								Path:        Ptr("/health"),
+								Response:    Ptr("ok"),
+								StatusCodes: Ptr([]string{"2??", "3??"}),
+								TLS:         Ptr(true),
 							},
 						},
 					},
@@ -2484,53 +2484,53 @@ func TestLoadBalancerAddServiceOptsToSchema(t *testing.T) {
 		"all set": {
 			Opts: LoadBalancerAddServiceOpts{
 				Protocol:        LoadBalancerServiceProtocolHTTP,
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &LoadBalancerAddServiceOptsHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Duration(5 * time.Minute),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * time.Minute),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
 					Certificates:   []*Certificate{{ID: 1}, {ID: 2}},
 				},
 				HealthCheck: &LoadBalancerAddServiceOptsHealthCheck{
 					Protocol: LoadBalancerServiceProtocolHTTP,
-					Port:     Int(80),
-					Interval: Duration(5 * time.Second),
-					Timeout:  Duration(1 * time.Second),
-					Retries:  Int(3),
+					Port:     Ptr(80),
+					Interval: Ptr(5 * time.Second),
+					Timeout:  Ptr(1 * time.Second),
+					Retries:  Ptr(3),
 					HTTP: &LoadBalancerAddServiceOptsHealthCheckHTTP{
-						Domain:      String("example.com"),
-						Path:        String("/health"),
-						Response:    String("ok"),
+						Domain:      Ptr("example.com"),
+						Path:        Ptr("/health"),
+						Response:    Ptr("ok"),
 						StatusCodes: []string{"2??", "3??"},
-						TLS:         Bool(true),
+						TLS:         Ptr(true),
 					},
 				},
 			},
 			Request: schema.LoadBalancerActionAddServiceRequest{
 				Protocol:        string(LoadBalancerServiceProtocolHTTP),
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &schema.LoadBalancerActionAddServiceRequestHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Int(5 * 60),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
-					Certificates:   intSlice([]int{1, 2}),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * 60),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
+					Certificates:   Ptr([]int{1, 2}),
 				},
 				HealthCheck: &schema.LoadBalancerActionAddServiceRequestHealthCheck{
 					Protocol: string(LoadBalancerServiceProtocolHTTP),
-					Port:     Int(80),
-					Interval: Int(5),
-					Timeout:  Int(1),
-					Retries:  Int(3),
+					Port:     Ptr(80),
+					Interval: Ptr(5),
+					Timeout:  Ptr(1),
+					Retries:  Ptr(3),
 					HTTP: &schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP{
-						Domain:      String("example.com"),
-						Path:        String("/health"),
-						Response:    String("ok"),
-						StatusCodes: stringSlice([]string{"2??", "3??"}),
-						TLS:         Bool(true),
+						Domain:      Ptr("example.com"),
+						Path:        Ptr("/health"),
+						Response:    Ptr("ok"),
+						StatusCodes: Ptr([]string{"2??", "3??"}),
+						TLS:         Ptr(true),
 					},
 				},
 			},
@@ -2538,26 +2538,26 @@ func TestLoadBalancerAddServiceOptsToSchema(t *testing.T) {
 		"no health check": {
 			Opts: LoadBalancerAddServiceOpts{
 				Protocol:        LoadBalancerServiceProtocolHTTP,
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &LoadBalancerAddServiceOptsHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Duration(5 * time.Minute),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * time.Minute),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
 					Certificates:   []*Certificate{{ID: 1}, {ID: 2}},
 				},
 			},
 			Request: schema.LoadBalancerActionAddServiceRequest{
 				Protocol:        string(LoadBalancerServiceProtocolHTTP),
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &schema.LoadBalancerActionAddServiceRequestHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Int(5 * 60),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
-					Certificates:   intSlice([]int{1, 2}),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * 60),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
+					Certificates:   Ptr([]int{1, 2}),
 				},
 				HealthCheck: nil,
 			},
@@ -2586,53 +2586,53 @@ func TestLoadBalancerUpdateServiceOptsToSchema(t *testing.T) {
 		"all set": {
 			Opts: LoadBalancerUpdateServiceOpts{
 				Protocol:        LoadBalancerServiceProtocolHTTP,
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &LoadBalancerUpdateServiceOptsHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Duration(5 * time.Minute),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * time.Minute),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
 					Certificates:   []*Certificate{{ID: 1}, {ID: 2}},
 				},
 				HealthCheck: &LoadBalancerUpdateServiceOptsHealthCheck{
 					Protocol: LoadBalancerServiceProtocolHTTP,
-					Port:     Int(80),
-					Interval: Duration(5 * time.Second),
-					Timeout:  Duration(1 * time.Second),
-					Retries:  Int(3),
+					Port:     Ptr(80),
+					Interval: Ptr(5 * time.Second),
+					Timeout:  Ptr(1 * time.Second),
+					Retries:  Ptr(3),
 					HTTP: &LoadBalancerUpdateServiceOptsHealthCheckHTTP{
-						Domain:      String("example.com"),
-						Path:        String("/health"),
-						Response:    String("ok"),
+						Domain:      Ptr("example.com"),
+						Path:        Ptr("/health"),
+						Response:    Ptr("ok"),
 						StatusCodes: []string{"2??", "3??"},
-						TLS:         Bool(true),
+						TLS:         Ptr(true),
 					},
 				},
 			},
 			Request: schema.LoadBalancerActionUpdateServiceRequest{
-				Protocol:        String(string(LoadBalancerServiceProtocolHTTP)),
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				Protocol:        Ptr(string(LoadBalancerServiceProtocolHTTP)),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &schema.LoadBalancerActionUpdateServiceRequestHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Int(5 * 60),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
-					Certificates:   intSlice([]int{1, 2}),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * 60),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
+					Certificates:   Ptr([]int{1, 2}),
 				},
 				HealthCheck: &schema.LoadBalancerActionUpdateServiceRequestHealthCheck{
-					Protocol: String(string(LoadBalancerServiceProtocolHTTP)),
-					Port:     Int(80),
-					Interval: Int(5),
-					Timeout:  Int(1),
-					Retries:  Int(3),
+					Protocol: Ptr(string(LoadBalancerServiceProtocolHTTP)),
+					Port:     Ptr(80),
+					Interval: Ptr(5),
+					Timeout:  Ptr(1),
+					Retries:  Ptr(3),
 					HTTP: &schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP{
-						Domain:      String("example.com"),
-						Path:        String("/health"),
-						Response:    String("ok"),
-						StatusCodes: stringSlice([]string{"2??", "3??"}),
-						TLS:         Bool(true),
+						Domain:      Ptr("example.com"),
+						Path:        Ptr("/health"),
+						Response:    Ptr("ok"),
+						StatusCodes: Ptr([]string{"2??", "3??"}),
+						TLS:         Ptr(true),
 					},
 				},
 			},
@@ -2640,26 +2640,26 @@ func TestLoadBalancerUpdateServiceOptsToSchema(t *testing.T) {
 		"no health check": {
 			Opts: LoadBalancerUpdateServiceOpts{
 				Protocol:        LoadBalancerServiceProtocolHTTP,
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &LoadBalancerUpdateServiceOptsHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Duration(5 * time.Minute),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * time.Minute),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
 					Certificates:   []*Certificate{{ID: 1}, {ID: 2}},
 				},
 			},
 			Request: schema.LoadBalancerActionUpdateServiceRequest{
-				Protocol:        String(string(LoadBalancerServiceProtocolHTTP)),
-				DestinationPort: Int(80),
-				Proxyprotocol:   Bool(true),
+				Protocol:        Ptr(string(LoadBalancerServiceProtocolHTTP)),
+				DestinationPort: Ptr(80),
+				Proxyprotocol:   Ptr(true),
 				HTTP: &schema.LoadBalancerActionUpdateServiceRequestHTTP{
-					CookieName:     String("keks"),
-					CookieLifetime: Int(5 * 60),
-					RedirectHTTP:   Bool(true),
-					StickySessions: Bool(true),
-					Certificates:   intSlice([]int{1, 2}),
+					CookieName:     Ptr("keks"),
+					CookieLifetime: Ptr(5 * 60),
+					RedirectHTTP:   Ptr(true),
+					StickySessions: Ptr(true),
+					Certificates:   Ptr([]int{1, 2}),
 				},
 				HealthCheck: nil,
 			},
diff --git a/hcloud/server.go b/hcloud/server.go
index 00bcb90..52ea7fa 100644
--- a/hcloud/server.go
+++ b/hcloud/server.go
@@ -458,13 +458,35 @@ func (c *ServerClient) Create(ctx context.Context, opts ServerCreateOpts) (Serve
 	return result, resp, nil
 }
 
+// ServerDeleteResult is the result of a delete server call.
+type ServerDeleteResult struct {
+	Action *Action
+}
+
 // Delete deletes a server.
+//
+// Deprecated: Use [ServerClient.DeleteWithResult] instead.
 func (c *ServerClient) Delete(ctx context.Context, server *Server) (*Response, error) {
+	_, resp, err := c.DeleteWithResult(ctx, server)
+	return resp, err
+}
+
+// DeleteWithResult deletes a server and returns the parsed response containing the action.
+func (c *ServerClient) DeleteWithResult(ctx context.Context, server *Server) (*ServerDeleteResult, *Response, error) {
 	req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/servers/%d", server.ID), nil)
 	if err != nil {
-		return nil, err
+		return &ServerDeleteResult{}, nil, err
 	}
-	return c.client.Do(req, nil)
+
+	var respBody schema.ServerDeleteResponse
+	resp, err := c.client.Do(req, &respBody)
+	if err != nil {
+		return &ServerDeleteResult{}, resp, err
+	}
+
+	return &ServerDeleteResult{
+		Action: ActionFromSchema(respBody.Action),
+	}, resp, nil
 }
 
 // ServerUpdateOpts specifies options for updating a server.
@@ -643,7 +665,7 @@ func (c *ServerClient) CreateImage(ctx context.Context, server *Server, opts *Se
 			reqBody.Description = opts.Description
 		}
 		if opts.Type != "" {
-			reqBody.Type = String(string(opts.Type))
+			reqBody.Type = Ptr(string(opts.Type))
 		}
 		if opts.Labels != nil {
 			reqBody.Labels = &opts.Labels
@@ -686,7 +708,7 @@ type ServerEnableRescueResult struct {
 // EnableRescue enables rescue mode for a server.
 func (c *ServerClient) EnableRescue(ctx context.Context, server *Server, opts ServerEnableRescueOpts) (ServerEnableRescueResult, *Response, error) {
 	reqBody := schema.ServerActionEnableRescueRequest{
-		Type: String(string(opts.Type)),
+		Type: Ptr(string(opts.Type)),
 	}
 	for _, sshKey := range opts.SSHKeys {
 		reqBody.SSHKeys = append(reqBody.SSHKeys, sshKey.ID)
@@ -735,8 +757,23 @@ type ServerRebuildOpts struct {
 	Image *Image
 }
 
+// ServerRebuildResult is the result of a create server call.
+type ServerRebuildResult struct {
+	Action       *Action
+	RootPassword string
+}
+
 // Rebuild rebuilds a server.
+//
+// Deprecated: Use [ServerClient.RebuildWithResult] instead.
 func (c *ServerClient) Rebuild(ctx context.Context, server *Server, opts ServerRebuildOpts) (*Action, *Response, error) {
+	result, resp, err := c.RebuildWithResult(ctx, server, opts)
+
+	return result.Action, resp, err
+}
+
+// RebuildWithResult rebuilds a server.
+func (c *ServerClient) RebuildWithResult(ctx context.Context, server *Server, opts ServerRebuildOpts) (ServerRebuildResult, *Response, error) {
 	reqBody := schema.ServerActionRebuildRequest{}
 	if opts.Image.ID != 0 {
 		reqBody.Image = opts.Image.ID
@@ -745,21 +782,29 @@ func (c *ServerClient) Rebuild(ctx context.Context, server *Server, opts ServerR
 	}
 	reqBodyData, err := json.Marshal(reqBody)
 	if err != nil {
-		return nil, nil, err
+		return ServerRebuildResult{}, nil, err
 	}
 
 	path := fmt.Sprintf("/servers/%d/actions/rebuild", server.ID)
 	req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData))
 	if err != nil {
-		return nil, nil, err
+		return ServerRebuildResult{}, nil, err
 	}
 
 	respBody := schema.ServerActionRebuildResponse{}
 	resp, err := c.client.Do(req, &respBody)
 	if err != nil {
-		return nil, resp, err
+		return ServerRebuildResult{}, resp, err
 	}
-	return ActionFromSchema(respBody.Action), resp, nil
+
+	result := ServerRebuildResult{
+		Action: ActionFromSchema(respBody.Action),
+	}
+	if respBody.RootPassword != nil {
+		result.RootPassword = *respBody.RootPassword
+	}
+
+	return result, resp, nil
 }
 
 // AttachISO attaches an ISO to a server.
@@ -811,7 +856,7 @@ func (c *ServerClient) DetachISO(ctx context.Context, server *Server) (*Action,
 func (c *ServerClient) EnableBackup(ctx context.Context, server *Server, window string) (*Action, *Response, error) {
 	reqBody := schema.ServerActionEnableBackupRequest{}
 	if window != "" {
-		reqBody.BackupWindow = String(window)
+		reqBody.BackupWindow = Ptr(window)
 	}
 	reqBodyData, err := json.Marshal(reqBody)
 	if err != nil {
@@ -964,10 +1009,10 @@ func (c *ServerClient) AttachToNetwork(ctx context.Context, server *Server, opts
 		Network: opts.Network.ID,
 	}
 	if opts.IP != nil {
-		reqBody.IP = String(opts.IP.String())
+		reqBody.IP = Ptr(opts.IP.String())
 	}
 	for _, aliasIP := range opts.AliasIPs {
-		reqBody.AliasIPs = append(reqBody.AliasIPs, String(aliasIP.String()))
+		reqBody.AliasIPs = append(reqBody.AliasIPs, Ptr(aliasIP.String()))
 	}
 	reqBodyData, err := json.Marshal(reqBody)
 	if err != nil {
diff --git a/hcloud/server_test.go b/hcloud/server_test.go
index 81681cd..cb1b821 100644
--- a/hcloud/server_test.go
+++ b/hcloud/server_test.go
@@ -12,6 +12,7 @@ import (
 	"time"
 
 	"github.com/google/go-cmp/cmp"
+
 	"github.com/hetznercloud/hcloud-go/hcloud/schema"
 )
 
@@ -341,7 +342,7 @@ func TestServersCreateWithoutSSHKeys(t *testing.T) {
 			Server: schema.Server{
 				ID: 1,
 			},
-			RootPassword: String("test"),
+			RootPassword: Ptr("test"),
 		})
 	})
 
@@ -399,7 +400,7 @@ func TestServersCreateWithVolumes(t *testing.T) {
 			{ID: 1},
 			{ID: 2},
 		},
-		Automount: Bool(true),
+		Automount: Ptr(true),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -846,7 +847,7 @@ func TestServersCreateWithLabels(t *testing.T) {
 			Server: schema.Server{
 				ID: 1,
 			},
-			RootPassword: String("test"),
+			RootPassword: Ptr("test"),
 		})
 	})
 
@@ -892,7 +893,7 @@ func TestServersCreateWithoutStarting(t *testing.T) {
 		Name:             "test",
 		ServerType:       &ServerType{ID: 1},
 		Image:            &Image{ID: 2},
-		StartAfterCreate: Bool(false),
+		StartAfterCreate: Ptr(false),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -1022,7 +1023,16 @@ func TestServersDelete(t *testing.T) {
 	env := newTestEnv()
 	defer env.Teardown()
 
-	env.Mux.HandleFunc("/servers/1", func(w http.ResponseWriter, r *http.Request) {})
+	env.Mux.HandleFunc("/servers/1", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != "DELETE" {
+			t.Error("expected DELETE")
+		}
+		json.NewEncoder(w).Encode(schema.ServerDeleteResponse{
+			Action: schema.Action{
+				ID: 2,
+			},
+		})
+	})
 
 	var (
 		ctx    = context.Background()
@@ -1034,6 +1044,34 @@ func TestServersDelete(t *testing.T) {
 	}
 }
 
+func TestServersDeleteWithResult(t *testing.T) {
+	env := newTestEnv()
+	defer env.Teardown()
+
+	env.Mux.HandleFunc("/servers/1", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != "DELETE" {
+			t.Error("expected DELETE")
+		}
+		json.NewEncoder(w).Encode(schema.ServerDeleteResponse{
+			Action: schema.Action{
+				ID: 2,
+			},
+		})
+	})
+
+	var (
+		ctx    = context.Background()
+		server = &Server{ID: 1}
+	)
+	result, _, err := env.Client.Server.DeleteWithResult(ctx, server)
+	if err != nil {
+		t.Fatalf("Server.Delete failed: %s", err)
+	}
+	if result.Action.ID != 2 {
+		t.Errorf("unexpected action ID: %v", result.Action.ID)
+	}
+}
+
 func TestServerClientUpdate(t *testing.T) {
 	var (
 		ctx    = context.Background()
@@ -1336,7 +1374,7 @@ func TestServerClientCreateImageWithOptions(t *testing.T) {
 	ctx := context.Background()
 	opts := &ServerCreateImageOpts{
 		Type:        ImageTypeBackup,
-		Description: String("my backup"),
+		Description: Ptr("my backup"),
 	}
 	result, _, err := env.Client.Server.CreateImage(ctx, &Server{ID: 1}, opts)
 	if err != nil {
@@ -1484,6 +1522,83 @@ func TestServerClientRebuild(t *testing.T) {
 	})
 }
 
+func TestServerClientRebuildWithResult(t *testing.T) {
+	var (
+		ctx    = context.Background()
+		server = &Server{ID: 1}
+	)
+
+	t.Run("with image ID", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/servers/1/actions/rebuild", func(w http.ResponseWriter, r *http.Request) {
+			var reqBody schema.ServerActionRebuildRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if id, ok := reqBody.Image.(float64); !ok || id != 1 {
+				t.Errorf("unexpected image ID: %v", reqBody.Image)
+			}
+			json.NewEncoder(w).Encode(schema.ServerActionRebuildResponse{
+				Action: schema.Action{
+					ID: 1,
+				},
+				RootPassword: Ptr("hetzner"),
+			})
+		})
+
+		opts := ServerRebuildOpts{
+			Image: &Image{ID: 1},
+		}
+		result, _, err := env.Client.Server.RebuildWithResult(ctx, server, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if result.Action.ID != 1 {
+			t.Errorf("unexpected action ID: %d", result.Action.ID)
+		}
+		if result.RootPassword != "hetzner" {
+			t.Errorf("unexpected root password: %s", result.RootPassword)
+		}
+	})
+
+	t.Run("with image name", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/servers/1/actions/rebuild", func(w http.ResponseWriter, r *http.Request) {
+			var reqBody schema.ServerActionRebuildRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if name, ok := reqBody.Image.(string); !ok || name != "debian-9" {
+				t.Errorf("unexpected image name: %v", reqBody.Image)
+			}
+			json.NewEncoder(w).Encode(schema.ServerActionRebuildResponse{
+				Action: schema.Action{
+					ID: 1,
+				},
+				RootPassword: nil,
+			})
+		})
+
+		opts := ServerRebuildOpts{
+			Image: &Image{Name: "debian-9"},
+		}
+		result, _, err := env.Client.Server.RebuildWithResult(ctx, server, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if result.Action.ID != 1 {
+			t.Errorf("unexpected action ID: %d", result.Action.ID)
+		}
+		if result.RootPassword != "" {
+			t.Errorf("unexpected root password: %s", result.RootPassword)
+		}
+	})
+}
+
 func TestServerClientAttachISO(t *testing.T) {
 	var (
 		ctx    = context.Background()
@@ -1773,8 +1888,8 @@ func TestServerClientChangeProtection(t *testing.T) {
 		})
 
 		opts := ServerChangeProtectionOpts{
-			Delete:  Bool(true),
-			Rebuild: Bool(true),
+			Delete:  Ptr(true),
+			Rebuild: Ptr(true),
 		}
 		action, _, err := env.Client.Server.ChangeProtection(ctx, server, opts)
 		if err != nil {
diff --git a/hcloud/volume.go b/hcloud/volume.go
index 93e221e..f939d89 100644
--- a/hcloud/volume.go
+++ b/hcloud/volume.go
@@ -210,7 +210,7 @@ func (c *VolumeClient) Create(ctx context.Context, opts VolumeCreateOpts) (Volum
 		reqBody.Labels = &opts.Labels
 	}
 	if opts.Server != nil {
-		reqBody.Server = Int(opts.Server.ID)
+		reqBody.Server = Ptr(opts.Server.ID)
 	}
 	if opts.Location != nil {
 		if opts.Location.ID != 0 {
diff --git a/hcloud/volume_test.go b/hcloud/volume_test.go
index fdb046b..025ee17 100644
--- a/hcloud/volume_test.go
+++ b/hcloud/volume_test.go
@@ -438,8 +438,8 @@ func TestVolumeClientCreateWithAutomount(t *testing.T) {
 		Size:      42,
 		Server:    &Server{ID: 1},
 		Labels:    map[string]string{"key": "value"},
-		Automount: Bool(true),
-		Format:    String("xfs"),
+		Automount: Ptr(true),
+		Format:    Ptr("xfs"),
 	}
 	result, _, err := env.Client.Volume.Create(ctx, opts)
 	if err != nil {
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..39a2b6e
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,6 @@
+{
+  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+  "extends": [
+    "config:base"
+  ]
+}

More details

Full run details

Historical runs