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"
+ ]
+}