Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package hcloud-cli for openSUSE:Factory checked in at 2026-01-17 14:56:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hcloud-cli (Old) and /work/SRC/openSUSE:Factory/.hcloud-cli.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hcloud-cli" Sat Jan 17 14:56:21 2026 rev:14 rq:1327708 version:1.60.0 Changes: -------- --- /work/SRC/openSUSE:Factory/hcloud-cli/hcloud-cli.changes 2026-01-12 10:34:08.837160892 +0100 +++ /work/SRC/openSUSE:Factory/.hcloud-cli.new.1928/hcloud-cli.changes 2026-01-17 14:57:12.385339872 +0100 @@ -1,0 +2,39 @@ +Fri Jan 16 15:21:41 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 1.60.0: + * Storage Box Subaccounts are no longer identified by username + Storage Box Subaccounts now have a name property, allowing + users to specify custom names for their Subaccounts. + More importantly, Storage Box Subaccounts (<subaccount>) are + now identified by id or name, instead of by id or username. + + hcloud storage-box subaccount describe <storage-box> <subaccount> + -hcloud storage-box subaccount describe my-storage-box u1337-sub1 + +hcloud storage-box subaccount describe my-storage-box my-subaccount + + Existing Subaccounts have been updated to use their username as + name value. + See our changelog for more details. + https://docs.hetzner.cloud/changelog#2026-01-15-storage-box-subaccount-name + * Features + - table: mark columns as deprecated and show warning (#1300) + - server: deprecate datacenter column (#1301) + - storage-box: add name property to subaccounts (#1315) + * Dependencies + - deps: update module github.com/hetznercloud/hcloud-go/v2 to + v2.35.0 (#1314) + - deps: update dependency go to v1.25.6 (#1312) + - deps: update golang.org/x/ (#1307) + - deps: update dependency jdx/mise to v2026.1.2 (#1310) + - deps: update dependency goreleaser/goreleaser to v2.13.3 + (#1308) + - deps: update dependency jdx/mise to v2026.1.1 (#1302) + - deps: update module github.com/hetznercloud/hcloud-go/v2 to + v2.34.0 (#1303) + - deps: update dependency jdx/mise to v2026 (#1297) + - deps: update module github.com/goccy/go-yaml to v1.19.2 + (#1299) + - deps: update dependency golangci/golangci-lint to v2.8.0 + (#1298) + +------------------------------------------------------------------- Old: ---- hcloud-cli-1.59.0.obscpio New: ---- hcloud-cli-1.60.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hcloud-cli.spec ++++++ --- /var/tmp/diff_new_pack.5pghcr/_old 2026-01-17 14:57:13.037367261 +0100 +++ /var/tmp/diff_new_pack.5pghcr/_new 2026-01-17 14:57:13.037367261 +0100 @@ -19,7 +19,7 @@ %define executable_name hcloud Name: hcloud-cli -Version: 1.59.0 +Version: 1.60.0 Release: 0 Summary: A command-line interface for Hetzner Cloud License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.5pghcr/_old 2026-01-17 14:57:13.093369614 +0100 +++ /var/tmp/diff_new_pack.5pghcr/_new 2026-01-17 14:57:13.105370118 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/hetznercloud/cli</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v1.59.0</param> + <param name="revision">v1.60.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.5pghcr/_old 2026-01-17 14:57:13.137371462 +0100 +++ /var/tmp/diff_new_pack.5pghcr/_new 2026-01-17 14:57:13.149371966 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/hetznercloud/cli</param> - <param name="changesrevision">e01a16ea40bdf213362675eeb94d61776619be01</param></service></servicedata> + <param name="changesrevision">b1697c7ebfc5cc33cafda3f462a03c36b718056c</param></service></servicedata> (No newline at EOF) ++++++ hcloud-cli-1.59.0.obscpio -> hcloud-cli-1.60.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/CHANGELOG.md new/hcloud-cli-1.60.0/CHANGELOG.md --- old/hcloud-cli-1.59.0/CHANGELOG.md 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/CHANGELOG.md 2026-01-16 15:53:42.000000000 +0100 @@ -1,5 +1,29 @@ # Changelog +## [v1.60.0](https://github.com/hetznercloud/cli/releases/tag/v1.60.0) + +### Storage Box Subaccounts are no longer identified by `username` + +Storage Box Subaccounts now have a `name` property, allowing users to specify custom names for their Subaccounts. + +More importantly, Storage Box Subaccounts (`<subaccount>`) are now identified by `id` or `name`, instead of by `id` or `username`. + +```diff + hcloud storage-box subaccount describe <storage-box> <subaccount> +-hcloud storage-box subaccount describe my-storage-box u1337-sub1 ++hcloud storage-box subaccount describe my-storage-box my-subaccount +``` + +Existing Subaccounts have been updated to use their `username` as `name` value. + +See our [changelog](https://docs.hetzner.cloud/changelog#2026-01-15-storage-box-subaccount-name) for more details. + +### Features + +- **table**: mark columns as deprecated and show warning (#1300) +- **server**: deprecate datacenter column (#1301) +- **storage-box**: add name property to subaccounts (#1315) + ## [v1.59.0](https://github.com/hetznercloud/cli/releases/tag/v1.59.0) ### Deprecation of `datacenter` attribute for Primary IPs and Servers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_create.md new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_create.md --- old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_create.md 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_create.md 2026-01-16 15:53:42.000000000 +0100 @@ -24,6 +24,7 @@ -h, --help help for create --home-directory string Home directory for the Subaccount (required) --label stringToString User-defined labels ('key=value') (can be specified multiple times) (default []) + --name string Name for the Subaccount -o, --output stringArray output options: json|yaml --password string Password for the Subaccount (required) --reachable-externally Whether the Storage Box should be accessible from outside the Hetzner network (true, false) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_list.md new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_list.md --- old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_list.md 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_list.md 2026-01-16 15:53:42.000000000 +0100 @@ -17,6 +17,7 @@ - home_directory - id - labels + - name - server - username diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_update.md new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_update.md --- old/hcloud-cli-1.59.0/docs/reference/manual/hcloud_storage-box_subaccount_update.md 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/docs/reference/manual/hcloud_storage-box_subaccount_update.md 2026-01-16 15:53:42.000000000 +0100 @@ -17,8 +17,9 @@ ### Options ``` - --description string Description of the Storage Box Snapshot + --description string Description of the Storage Box Subaccount -h, --help help for update + --name string Name of the Storage Box Subaccount ``` ### Options inherited from parent commands diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/docs/tutorials/setup-hcloud-cli.md new/hcloud-cli-1.60.0/docs/tutorials/setup-hcloud-cli.md --- old/hcloud-cli-1.59.0/docs/tutorials/setup-hcloud-cli.md 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/docs/tutorials/setup-hcloud-cli.md 2026-01-16 15:53:42.000000000 +0100 @@ -45,9 +45,16 @@ brew install hcloud ``` -### 1.4 Installation using scoop +### 1.4 Installation on Windows using WinGet or Scoop -On Windows, you can install `hcloud` using scoop: +> [!WARNING] +> The WinGet and Scoop package entries are not maintained by Hetzner. + +On Windows, you can install `hcloud` using WinGet (Windows Package Manager) or Scoop: + +```bash +winget install HetznerCloud.CLI +``` ```bash scoop install hcloud diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/go.mod new/hcloud-cli-1.60.0/go.mod --- old/hcloud-cli-1.59.0/go.mod 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/go.mod 2026-01-16 15:53:42.000000000 +0100 @@ -2,7 +2,7 @@ go 1.24.0 -toolchain go1.25.5 +toolchain go1.25.6 require ( github.com/BurntSushi/toml v1.6.0 @@ -10,9 +10,9 @@ github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/fatih/structs v1.1.0 - github.com/goccy/go-yaml v1.19.1 + github.com/goccy/go-yaml v1.19.2 github.com/guptarohit/asciigraph v0.7.3 - github.com/hetznercloud/hcloud-go/v2 v2.33.0 + github.com/hetznercloud/hcloud-go/v2 v2.35.0 github.com/jedib0t/go-pretty/v6 v6.7.8 github.com/spf13/cast v1.10.0 github.com/spf13/cobra v1.10.2 @@ -21,11 +21,11 @@ github.com/stretchr/testify v1.11.1 github.com/swaggest/assertjson v1.10.0 go.uber.org/mock v0.6.0 - golang.org/x/crypto v0.46.0 - golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 - golang.org/x/net v0.48.0 - golang.org/x/term v0.38.0 - golang.org/x/text v0.32.0 + golang.org/x/crypto v0.47.0 + golang.org/x/exp v0.0.0-20260112195511-716be5621a96 + golang.org/x/net v0.49.0 + golang.org/x/term v0.39.0 + golang.org/x/text v0.33.0 ) require ( @@ -59,7 +59,7 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect google.golang.org/protobuf v1.36.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/go.sum new/hcloud-cli-1.60.0/go.sum --- old/hcloud-cli-1.59.0/go.sum 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/go.sum 2026-01-16 15:53:42.000000000 +0100 @@ -30,14 +30,14 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE= -github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/guptarohit/asciigraph v0.7.3 h1:p05XDDn7cBTWiBqWb30mrwxd6oU0claAjqeytllnsPY= github.com/guptarohit/asciigraph v0.7.3/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= -github.com/hetznercloud/hcloud-go/v2 v2.33.0 h1:g9hwuo60IXbupXJCYMlO4xDXgxxMPuFk31iOpLXDCV4= -github.com/hetznercloud/hcloud-go/v2 v2.33.0/go.mod h1:GzYEl7slIGKc6Ttt08hjiJvGj8/PbWzcQf6IUi02dIs= +github.com/hetznercloud/hcloud-go/v2 v2.35.0 h1:bXYsXZnyn6cbSOpvrs3/iwJ/cakzlsCqYDFLOU8ILFs= +github.com/hetznercloud/hcloud-go/v2 v2.35.0/go.mod h1:MnN/QJEa/RYNQiiVoJjNHPntM7Z1wlYPgJ2HA40/cDE= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -118,19 +118,19 @@ go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= -golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= +golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/base/list.go new/hcloud-cli-1.60.0/internal/cmd/base/list.go --- old/hcloud-cli-1.59.0/internal/cmd/base/list.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/base/list.go 2026-01-16 15:53:42.000000000 +0100 @@ -163,6 +163,13 @@ t := output.NewTable[T](out) lc.OutputTable(t, s.Client()) + + warnings, _ := t.ValidateColumns(cols) + // invalid columns are already checked in output.validateOutputFlag(), we only need the warnings here + for _, warning := range warnings { + cmd.PrintErrln("Warning:", warning) + } + if !outOpts.IsSet("noheader") { t.WriteHeader(cols) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/context/list.go new/hcloud-cli-1.60.0/internal/cmd/context/list.go --- old/hcloud-cli-1.59.0/internal/cmd/context/list.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/context/list.go 2026-01-16 15:53:42.000000000 +0100 @@ -43,9 +43,13 @@ } tw := newListOutputTable(cmd.OutOrStdout()) - if err := tw.ValidateColumns(cols); err != nil { + warnings, err := tw.ValidateColumns(cols) + if err != nil { return err } + for _, warning := range warnings { + cmd.PrintErrln("Warning:", warning) + } if !outOpts.IsSet("noheader") { tw.WriteHeader(cols) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/output/output.go new/hcloud-cli-1.60.0/internal/cmd/output/output.go --- old/hcloud-cli-1.59.0/internal/cmd/output/output.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/output/output.go 2026-01-16 15:53:42.000000000 +0100 @@ -174,6 +174,7 @@ fieldMapping: map[string]FieldFn[T]{}, fieldAlias: map[string]string{}, allowedFields: map[string]bool{}, + deprecations: map[string]string{}, } } @@ -187,6 +188,7 @@ fieldMapping map[string]FieldFn[T] fieldAlias map[string]string allowedFields map[string]bool + deprecations map[string]string } // Columns returns a list of known output columns. @@ -212,6 +214,13 @@ return o } +// MarkFieldAsDeprecated marks the specified field as deprecated. The message will be printed +// to stderr if the column is used. +func (o *Table[T]) MarkFieldAsDeprecated(field string, message string) *Table[T] { + o.deprecations[field] = message + return o +} + // AddAllowedFields reads all first level fieldnames of the struct and allows them to be used. func (o *Table[T]) AddAllowedFields(obj T) *Table[T] { v := reflect.ValueOf(obj) @@ -250,18 +259,21 @@ return o } -// ValidateColumns returns an error if invalid columns are specified. -func (o *Table[T]) ValidateColumns(cols []string) error { - var invalidCols []string +// ValidateColumns returns a list of warnings for the used columns and an error if invalid columns are specified. +func (o *Table[T]) ValidateColumns(cols []string) ([]string, error) { + var warnings, invalidCols []string for _, col := range cols { + if warning, isDeprecated := o.deprecations[strings.ToLower(col)]; isDeprecated { + warnings = append(warnings, warning) + } if _, ok := o.allowedFields[strings.ToLower(col)]; !ok { invalidCols = append(invalidCols, col) } } if len(invalidCols) > 0 { - return fmt.Errorf("invalid table columns: %s", strings.Join(invalidCols, ",")) + return warnings, fmt.Errorf("invalid table columns: %s", strings.Join(invalidCols, ",")) } - return nil + return warnings, nil } // WriteHeader writes the table header. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/output/output_test.go new/hcloud-cli-1.60.0/internal/cmd/output/output_test.go --- old/hcloud-cli-1.59.0/internal/cmd/output/output_test.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/output/output_test.go 2026-01-16 15:53:42.000000000 +0100 @@ -51,11 +51,18 @@ assert.Contains(t, to.fieldMapping, "leeroy jenkins") }) + t.Run("MarkFieldAsDeprecated", func(t *testing.T) { + to.MarkFieldAsDeprecated("name", "This field is deprecated") + + assert.Contains(t, to.deprecations, "name") + }) + t.Run("ValidateColumns", func(t *testing.T) { - err := to.ValidateColumns([]string{"non-existent", "NAME"}) + warnings, err := to.ValidateColumns([]string{"non-existent", "NAME"}) require.ErrorContains(t, err, "non-existent") assert.NotContains(t, err.Error(), "name") + assert.Contains(t, warnings, "This field is deprecated") }) t.Run("WriteHeader", func(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/server/list.go new/hcloud-cli-1.60.0/internal/cmd/server/list.go --- old/hcloud-cli-1.59.0/internal/cmd/server/list.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/server/list.go 2026-01-16 15:53:42.000000000 +0100 @@ -93,7 +93,6 @@ return server.Datacenter.Name } return "-" - }). AddFieldFn("location", func(server *hcloud.Server) string { return server.Location.Name @@ -140,7 +139,8 @@ return "-" } return server.PlacementGroup.Name - }) + }). + MarkFieldAsDeprecated("datacenter", "The datacenter column is deprecated. Use location column instead.") }, Schema: hcloud.SchemaFromServer, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/create.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/create.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/create.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/create.go 2026-01-16 15:53:42.000000000 +0100 @@ -24,6 +24,8 @@ DisableFlagsInUseLine: true, } + cmd.Flags().String("name", "", "Name for the Subaccount") + cmd.Flags().String("password", "", "Password for the Subaccount (required)") _ = cmd.MarkFlagRequired("password") @@ -44,6 +46,7 @@ }, Run: func(s state.State, cmd *cobra.Command, args []string) (*hcloud.StorageBoxSubaccount, any, error) { storageBoxIDOrName := args[0] + name, _ := cmd.Flags().GetString("name") password, _ := cmd.Flags().GetString("password") homeDirectory, _ := cmd.Flags().GetString("home-directory") description, _ := cmd.Flags().GetString("description") @@ -81,6 +84,7 @@ } opts := hcloud.StorageBoxSubaccountCreateOpts{ + Name: name, HomeDirectory: homeDirectory, Password: password, Description: description, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/create_test.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/create_test.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/create_test.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/create_test.go 2026-01-16 15:53:42.000000000 +0100 @@ -81,6 +81,7 @@ sbs := &hcloud.StorageBoxSubaccount{ ID: 42, + Name: "u1337-sub1", Username: "u1337-sub1", HomeDirectory: "my_backups/host01.my.company", Server: "u1337-sub1.your-storagebox.de", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/describe.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/describe.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/describe.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/describe.go 2026-01-16 15:53:42.000000000 +0100 @@ -45,6 +45,7 @@ }, PrintText: func(_ state.State, _ *cobra.Command, out io.Writer, subaccount *hcloud.StorageBoxSubaccount) error { fmt.Fprintf(out, "ID:\t%d\n", subaccount.ID) + fmt.Fprintf(out, "Name:\t%s\n", subaccount.Name) fmt.Fprintf(out, "Description:\t%s\n", util.NA(subaccount.Description)) fmt.Fprintf(out, "Created:\t%s (%s)\n", util.Datetime(subaccount.Created), humanize.Time(subaccount.Created)) fmt.Fprintf(out, "Username:\t%s\n", subaccount.Username) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/describe_test.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/describe_test.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/describe_test.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/describe_test.go 2026-01-16 15:53:42.000000000 +0100 @@ -30,6 +30,7 @@ } sbs := &hcloud.StorageBoxSubaccount{ ID: 42, + Name: "u1337-sub1", Username: "u1337-sub1", HomeDirectory: "my_backups/host01.my.company", Server: "u1337-sub1.your-storagebox.de", @@ -60,6 +61,7 @@ out, errOut, err := fx.Run(cmd, []string{"my-storage-box", "42"}) expOut := fmt.Sprintf(`ID: 42 +Name: u1337-sub1 Description: host01 backup Created: 2016-01-30 23:55:00 UTC (%s) Username: u1337-sub1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/list.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/list.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/list.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/list.go 2026-01-16 15:53:42.000000000 +0100 @@ -23,7 +23,7 @@ ResourceNamePlural: "Storage Box Subaccounts", JSONKeyGetByName: "subaccounts", - DefaultColumns: []string{"id", "username", "home_directory", "description", "server", "age"}, + DefaultColumns: []string{"id", "name", "home_directory", "description", "username", "server", "age"}, ValidArgsFunction: func(client hcapi2.Client) cobra.CompletionFunc { return cmpl.SuggestCandidatesF(client.StorageBox().Names) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/list_test.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/list_test.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/list_test.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/list_test.go 2026-01-16 15:53:42.000000000 +0100 @@ -29,6 +29,7 @@ } sbs := &hcloud.StorageBoxSubaccount{ ID: 42, + Name: "u1337-sub1", Username: "u1337-sub1", HomeDirectory: "my_backups/host01.my.company", Server: "u1337-sub1.your-storagebox.de", @@ -65,8 +66,8 @@ out, errOut, err := fx.Run(cmd, []string{"test"}) - expOut := fmt.Sprintf(`ID USERNAME HOME DIRECTORY DESCRIPTION SERVER AGE -42 u1337-sub1 my_backups/host01.my.company host01 backup u1337-sub1.your-storagebox.de %s + expOut := fmt.Sprintf(`ID NAME HOME DIRECTORY DESCRIPTION USERNAME SERVER AGE +42 u1337-sub1 my_backups/host01.my.company host01 backup u1337-sub1 u1337-sub1.your-storagebox.de %s `, util.Age(sbs.Created, time.Now())) require.NoError(t, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/testdata/create_response.json new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/testdata/create_response.json --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/testdata/create_response.json 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/testdata/create_response.json 2026-01-16 15:53:42.000000000 +0100 @@ -1,6 +1,7 @@ { "subaccount": { "id": 42, + "name": "u1337-sub1", "username": "u1337-sub1", "home_directory": "my_backups/host01.my.company", "server": "u1337-sub1.your-storagebox.de", @@ -20,4 +21,4 @@ "created": "2016-01-30T23:55:00Z", "storage_box": 42 } -} \ No newline at end of file +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/update.go new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/update.go --- old/hcloud-cli-1.59.0/internal/cmd/storagebox/subaccount/update.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/cmd/storagebox/subaccount/update.go 2026-01-16 15:53:42.000000000 +0100 @@ -37,11 +37,16 @@ return s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) }, DefineFlags: func(cmd *cobra.Command) { - cmd.Flags().String("description", "", "Description of the Storage Box Snapshot") - cmd.MarkFlagsOneRequired("description") + cmd.Flags().String("name", "", "Name of the Storage Box Subaccount") + cmd.Flags().String("description", "", "Description of the Storage Box Subaccount") + cmd.MarkFlagsOneRequired("name", "description") }, Update: func(s state.State, cmd *cobra.Command, subaccount *hcloud.StorageBoxSubaccount, _ map[string]pflag.Value) error { var opts hcloud.StorageBoxSubaccountUpdateOpts + if cmd.Flags().Changed("name") { + name, _ := cmd.Flags().GetString("name") + opts.Name = name + } if cmd.Flags().Changed("description") { description, _ := cmd.Flags().GetString("description") opts.Description = &description diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/hcapi2/mock/zz_storage_box_client_mock.go new/hcloud-cli-1.60.0/internal/hcapi2/mock/zz_storage_box_client_mock.go --- old/hcloud-cli-1.59.0/internal/hcapi2/mock/zz_storage_box_client_mock.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/hcapi2/mock/zz_storage_box_client_mock.go 2026-01-16 15:53:42.000000000 +0100 @@ -420,9 +420,9 @@ } // GetSubaccount mocks base method. -func (m *MockStorageBoxClient) GetSubaccount(ctx context.Context, storageBox *hcloud.StorageBox, idOrUsername string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { +func (m *MockStorageBoxClient) GetSubaccount(ctx context.Context, storageBox *hcloud.StorageBox, idOrName string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubaccount", ctx, storageBox, idOrUsername) + ret := m.ctrl.Call(m, "GetSubaccount", ctx, storageBox, idOrName) ret0, _ := ret[0].(*hcloud.StorageBoxSubaccount) ret1, _ := ret[1].(*hcloud.Response) ret2, _ := ret[2].(error) @@ -430,9 +430,9 @@ } // GetSubaccount indicates an expected call of GetSubaccount. -func (mr *MockStorageBoxClientMockRecorder) GetSubaccount(ctx, storageBox, idOrUsername any) *gomock.Call { +func (mr *MockStorageBoxClientMockRecorder) GetSubaccount(ctx, storageBox, idOrName any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccount", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccount), ctx, storageBox, idOrUsername) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccount", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccount), ctx, storageBox, idOrName) } // GetSubaccountByID mocks base method. @@ -451,6 +451,22 @@ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccountByID", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccountByID), ctx, storageBox, id) } +// GetSubaccountByName mocks base method. +func (m *MockStorageBoxClient) GetSubaccountByName(ctx context.Context, storageBox *hcloud.StorageBox, name string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubaccountByName", ctx, storageBox, name) + ret0, _ := ret[0].(*hcloud.StorageBoxSubaccount) + ret1, _ := ret[1].(*hcloud.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetSubaccountByName indicates an expected call of GetSubaccountByName. +func (mr *MockStorageBoxClientMockRecorder) GetSubaccountByName(ctx, storageBox, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccountByName", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccountByName), ctx, storageBox, name) +} + // GetSubaccountByUsername mocks base method. func (m *MockStorageBoxClient) GetSubaccountByUsername(ctx context.Context, storageBox *hcloud.StorageBox, username string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { m.ctrl.T.Helper() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/internal/version/version.go new/hcloud-cli-1.60.0/internal/version/version.go --- old/hcloud-cli-1.59.0/internal/version/version.go 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/internal/version/version.go 2026-01-16 15:53:42.000000000 +0100 @@ -2,7 +2,7 @@ var ( // version is a semver version (https://semver.org). - version = "1.59.0" // x-releaser-pleaser-version + version = "1.60.0" // x-releaser-pleaser-version // versionPrerelease is a semver version pre-release identifier (https://semver.org). // diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.59.0/mise.toml new/hcloud-cli-1.60.0/mise.toml --- old/hcloud-cli-1.59.0/mise.toml 2026-01-05 17:16:10.000000000 +0100 +++ new/hcloud-cli-1.60.0/mise.toml 2026-01-16 15:53:42.000000000 +0100 @@ -1,7 +1,7 @@ [tools] -go = "1.25.5" +go = "1.25.6" "go:go.uber.org/mock/mockgen" = "v0.6.0" -"github:golangci/golangci-lint" = "2.7.2" # renovate: datasource=github-releases depName=golangci/golangci-lint -"github:goreleaser/goreleaser" = "v2.13.2" # renovate: datasource=github-releases depName=goreleaser/goreleaser +"github:golangci/golangci-lint" = "2.8.0" # renovate: datasource=github-releases depName=golangci/golangci-lint +"github:goreleaser/goreleaser" = "v2.13.3" # renovate: datasource=github-releases depName=goreleaser/goreleaser "github:anchore/quill" = "v0.5.1" # renovate: datasource=github-releases depName=anchore/quill "github:jstemmer/go-junit-report" = "v2.1.0" # renovate: datasource=github-releases depName=jstemmer/go-junit-report ++++++ hcloud-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.5pghcr/_old 2026-01-17 14:57:13.729396331 +0100 +++ /var/tmp/diff_new_pack.5pghcr/_new 2026-01-17 14:57:13.741396835 +0100 @@ -1,5 +1,5 @@ name: hcloud-cli -version: 1.59.0 -mtime: 1767629770 -commit: e01a16ea40bdf213362675eeb94d61776619be01 +version: 1.60.0 +mtime: 1768575222 +commit: b1697c7ebfc5cc33cafda3f462a03c36b718056c ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/goccy/go-yaml/decode.go new/vendor/github.com/goccy/go-yaml/decode.go --- old/vendor/github.com/goccy/go-yaml/decode.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/goccy/go-yaml/decode.go 2026-01-16 15:53:42.000000000 +0100 @@ -465,8 +465,10 @@ } return v.Interface(), nil } - aliasName := n.Value.GetToken().Value - return nil, errors.ErrSyntax(fmt.Sprintf("could not find alias %q", aliasName), n.Value.GetToken()) + if node, exists := d.anchorNodeMap[text]; exists { + return d.nodeToValue(ctx, node) + } + return nil, errors.ErrSyntax(fmt.Sprintf("could not find alias %q", text), n.Value.GetToken()) case *ast.LiteralNode: return n.Value.GetValue(), nil case *ast.MappingKeyNode: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action.go 2026-01-16 15:53:42.000000000 +0100 @@ -65,19 +65,26 @@ } func (e ActionError) Error() string { - action := e.Action() - if action != nil { + if e.action != nil { // For easier debugging, the error string contains the Action ID. - return fmt.Sprintf("%s (%s, %d)", e.Message, e.Code, action.ID) + return fmt.Sprintf("%s (%s, %d)", e.Message, e.Code, e.action.ID) } return fmt.Sprintf("%s (%s)", e.Message, e.Code) } func (a *Action) Error() error { - if a.ErrorCode != "" && a.ErrorMessage != "" { + if a.Status == ActionStatusError || a.ErrorCode != "" { + code := a.ErrorCode + if code == "" { + code = "<unknown>" + } + message := a.ErrorMessage + if message == "" { + message = "Unknown error" + } return ActionError{ - Code: a.ErrorCode, - Message: a.ErrorMessage, + Code: code, + Message: message, action: a, } } @@ -86,7 +93,7 @@ // ActionClient is a client for the actions API. type ActionClient struct { - action *ResourceActionClient + action *ResourceActionClient[noopResource] } // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. @@ -116,7 +123,7 @@ return vals } -// List returns a list of actions for a specific page. +// List returns a paginated list of actions. // // Please note that filters specified in opts are not taken into account // when their value corresponds to their zero value or when they are empty. @@ -143,12 +150,12 @@ } // ResourceActionClient is a client for the actions API exposed by the resource. -type ResourceActionClient struct { +type ResourceActionClient[R actionSupporter] struct { resource string client *Client } -func (c *ResourceActionClient) getBaseURL() string { +func (c *ResourceActionClient[R]) getBaseURL() string { if c.resource == "" { return "" } @@ -157,7 +164,7 @@ } // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. -func (c *ResourceActionClient) GetByID(ctx context.Context, id int64) (*Action, *Response, error) { +func (c *ResourceActionClient[R]) GetByID(ctx context.Context, id int64) (*Action, *Response, error) { opPath := c.getBaseURL() + "/actions/%d" ctx = ctxutil.SetOpPath(ctx, opPath) @@ -173,11 +180,11 @@ return ActionFromSchema(respBody.Action), resp, nil } -// List returns a list of actions for a specific page. +// List returns a paginated list of actions. // // Please note that filters specified in opts are not taken into account // when their value corresponds to their zero value or when they are empty. -func (c *ResourceActionClient) List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) { +func (c *ResourceActionClient[R]) List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) { opPath := c.getBaseURL() + "/actions?%s" ctx = ctxutil.SetOpPath(ctx, opPath) @@ -192,7 +199,7 @@ } // All returns all actions for the given options. -func (c *ResourceActionClient) All(ctx context.Context, opts ActionListOpts) ([]*Action, error) { +func (c *ResourceActionClient[R]) All(ctx context.Context, opts ActionListOpts) ([]*Action, error) { if opts.ListOpts.PerPage == 0 { opts.ListOpts.PerPage = 50 } @@ -201,3 +208,44 @@ return c.List(ctx, opts) }) } + +type actionSupporter interface { + pathID() (string, error) +} + +// noopResource is used by the [ActionClient] to satisfy its underlying +// [ResourceActionClient] generic type. +type noopResource struct{} + +func (noopResource) pathID() (string, error) { return "", nil } + +// ListFor returns a paginated list of actions for the given Resource. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *ResourceActionClient[R]) ListFor(ctx context.Context, resource R, opts ActionListOpts) ([]*Action, *Response, error) { + opPath := c.getBaseURL() + "/%s/actions?%s" + ctx = ctxutil.SetOpPath(ctx, opPath) + + id, err := resource.pathID() + if err != nil { + return nil, nil, invalidArgument("resource", resource, err) + } + + reqPath := fmt.Sprintf(opPath, id, opts.values().Encode()) + + respBody, resp, err := getRequest[schema.ActionListResponse](ctx, c.client, reqPath) + if err != nil { + return nil, resp, err + } + + return allFromSchemaFunc(respBody.Actions, ActionFromSchema), resp, nil +} + +// AllFor returns all actions for the given Resource. +func (c *ResourceActionClient[R]) AllFor(ctx context.Context, resource R, opts ActionListOpts) ([]*Action, error) { + return iterPages(func(page int) ([]*Action, *Response, error) { + opts.Page = page + return c.ListFor(ctx, resource, opts) + }) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/certificate.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/certificate.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/certificate.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/certificate.go 2026-01-16 15:53:42.000000000 +0100 @@ -4,6 +4,7 @@ "context" "fmt" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -61,8 +62,8 @@ // IsFailed returns true if either the Issuance or the Renewal of a certificate // failed. In this case the FailureReason field details the nature of the // failure. -func (st *CertificateStatus) IsFailed() bool { - return st.Issuance == CertificateStatusTypeFailed || st.Renewal == CertificateStatusTypeFailed +func (o *CertificateStatus) IsFailed() bool { + return o.Issuance == CertificateStatusTypeFailed || o.Renewal == CertificateStatusTypeFailed } // Certificate represents a certificate in the Hetzner Cloud. @@ -81,6 +82,13 @@ UsedBy []CertificateUsedByRef } +func (o *Certificate) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // CertificateCreateResult is the result of creating a certificate. type CertificateCreateResult struct { Certificate *Certificate @@ -90,7 +98,7 @@ // CertificateClient is a client for the Certificates API. type CertificateClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Certificate] } // GetByID retrieves a Certificate by its ID. If the Certificate does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client.go 2026-01-16 15:53:42.000000000 +0100 @@ -291,26 +291,26 @@ client.handler = assembleHandlerChain(client) // Cloud API - client.Action = ActionClient{action: &ResourceActionClient{client: client}} + client.Action = ActionClient{action: &ResourceActionClient[noopResource]{client: client}} client.Datacenter = DatacenterClient{client: client} - client.FloatingIP = FloatingIPClient{client: client, Action: &ResourceActionClient{client: client, resource: "floating_ips"}} - client.Image = ImageClient{client: client, Action: &ResourceActionClient{client: client, resource: "images"}} + client.FloatingIP = FloatingIPClient{client: client, Action: &ResourceActionClient[*FloatingIP]{client: client, resource: "floating_ips"}} + client.Image = ImageClient{client: client, Action: &ResourceActionClient[*Image]{client: client, resource: "images"}} client.ISO = ISOClient{client: client} client.Location = LocationClient{client: client} - client.Network = NetworkClient{client: client, Action: &ResourceActionClient{client: client, resource: "networks"}} + client.Network = NetworkClient{client: client, Action: &ResourceActionClient[*Network]{client: client, resource: "networks"}} client.Pricing = PricingClient{client: client} - client.Server = ServerClient{client: client, Action: &ResourceActionClient{client: client, resource: "servers"}} + client.Server = ServerClient{client: client, Action: &ResourceActionClient[*Server]{client: client, resource: "servers"}} client.ServerType = ServerTypeClient{client: client} client.SSHKey = SSHKeyClient{client: client} - client.Volume = VolumeClient{client: client, Action: &ResourceActionClient{client: client, resource: "volumes"}} - client.LoadBalancer = LoadBalancerClient{client: client, Action: &ResourceActionClient{client: client, resource: "load_balancers"}} + client.Volume = VolumeClient{client: client, Action: &ResourceActionClient[*Volume]{client: client, resource: "volumes"}} + client.LoadBalancer = LoadBalancerClient{client: client, Action: &ResourceActionClient[*LoadBalancer]{client: client, resource: "load_balancers"}} client.LoadBalancerType = LoadBalancerTypeClient{client: client} - client.Certificate = CertificateClient{client: client, Action: &ResourceActionClient{client: client, resource: "certificates"}} - client.Firewall = FirewallClient{client: client, Action: &ResourceActionClient{client: client, resource: "firewalls"}} + client.Certificate = CertificateClient{client: client, Action: &ResourceActionClient[*Certificate]{client: client, resource: "certificates"}} + client.Firewall = FirewallClient{client: client, Action: &ResourceActionClient[*Firewall]{client: client, resource: "firewalls"}} client.PlacementGroup = PlacementGroupClient{client: client} client.RDNS = RDNSClient{client: client} - client.PrimaryIP = PrimaryIPClient{client: client, Action: &ResourceActionClient{client: client, resource: "primary_ips"}} - client.Zone = ZoneClient{client: client, Action: &ResourceActionClient{client: client, resource: "zones"}} + client.PrimaryIP = PrimaryIPClient{client: client, Action: &ResourceActionClient[*PrimaryIP]{client: client, resource: "primary_ips"}} + client.Zone = ZoneClient{client: client, Action: &ResourceActionClient[*Zone]{client: client, resource: "zones"}} // Hetzner API @@ -321,7 +321,7 @@ *hetznerClient = *client hetznerClient.endpoint = hetznerClient.hetznerEndpoint - client.StorageBox = StorageBoxClient{client: hetznerClient, Action: &ResourceActionClient{client: hetznerClient, resource: "storage_boxes"}} + client.StorageBox = StorageBoxClient{client: hetznerClient, Action: &ResourceActionClient[*StorageBox]{client: hetznerClient, resource: "storage_boxes"}} client.StorageBoxType = StorageBoxTypeClient{client: hetznerClient} return client diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client_handler_retry.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client_handler_retry.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client_handler_retry.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client_handler_retry.go 2026-01-16 15:53:42.000000000 +0100 @@ -66,6 +66,8 @@ return true case ErrorCodeRateLimitExceeded: return true + case ErrorCodeTimeout: + return true } case errors.Is(err, ErrStatusCode): switch resp.Response.StatusCode { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go 2026-01-16 15:53:42.000000000 +0100 @@ -29,30 +29,30 @@ } // IsDeprecated returns true if the resource is marked as deprecated. -func (d DeprecatableResource) IsDeprecated() bool { - return d.Deprecation != nil +func (o DeprecatableResource) IsDeprecated() bool { + return o.Deprecation != nil } // UnavailableAfter returns the time that the deprecated resource will be removed from the API. // This only returns a valid value if [Deprecatable.IsDeprecated] returned true. -func (d DeprecatableResource) UnavailableAfter() time.Time { - if !d.IsDeprecated() { +func (o DeprecatableResource) UnavailableAfter() time.Time { + if !o.IsDeprecated() { // Return "null" time if resource is not deprecated return time.Unix(0, 0) } - return d.Deprecation.UnavailableAfter + return o.Deprecation.UnavailableAfter } // DeprecationAnnounced returns the time that the deprecation of this resource was announced. // This only returns a valid value if [Deprecatable.IsDeprecated] returned true. -func (d DeprecatableResource) DeprecationAnnounced() time.Time { - if !d.IsDeprecated() { +func (o DeprecatableResource) DeprecationAnnounced() time.Time { + if !o.IsDeprecated() { // Return "null" time if resource is not deprecated return time.Unix(0, 0) } - return d.Deprecation.Announced + return o.Deprecation.Announced } // Make sure that all expected Resources actually implement the interface. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go 2026-01-16 15:53:42.000000000 +0100 @@ -5,6 +5,7 @@ "fmt" "net" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -21,6 +22,13 @@ AppliedTo []FirewallResource } +func (o *Firewall) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // FirewallRule represents a Firewall's rules. type FirewallRule struct { Direction FirewallRuleDirection @@ -91,7 +99,7 @@ // FirewallClient is a client for the Firewalls API. type FirewallClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Firewall] } // GetByID retrieves a Firewall by its ID. If the Firewall does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go 2026-01-16 15:53:42.000000000 +0100 @@ -5,6 +5,7 @@ "fmt" "net" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -28,11 +29,18 @@ Name string } +func (o *FloatingIP) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // DNSPtrForIP returns the reverse DNS pointer of the IP address. // // Deprecated: Use GetDNSPtrForIP instead. -func (f *FloatingIP) DNSPtrForIP(ip net.IP) string { - return f.DNSPtr[ip.String()] +func (o *FloatingIP) DNSPtrForIP(ip net.IP) string { + return o.DNSPtr[ip.String()] } // FloatingIPProtection represents the protection level of a Floating IP. @@ -51,11 +59,11 @@ // changeDNSPtr changes or resets the reverse DNS pointer for an IP address. // Pass a nil ptr to reset the reverse DNS pointer to its default value. -func (f *FloatingIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { +func (o *FloatingIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { const opPath = "/floating_ips/%d/actions/change_dns_ptr" ctx = ctxutil.SetOpPath(ctx, opPath) - reqPath := fmt.Sprintf(opPath, f.ID) + reqPath := fmt.Sprintf(opPath, o.ID) reqBody := schema.FloatingIPActionChangeDNSPtrRequest{ IP: ip.String(), @@ -72,8 +80,8 @@ // GetDNSPtrForIP searches for the dns assigned to the given IP address. // It returns an error if there is no dns set for the given IP address. -func (f *FloatingIP) GetDNSPtrForIP(ip net.IP) (string, error) { - dns, ok := f.DNSPtr[ip.String()] +func (o *FloatingIP) GetDNSPtrForIP(ip net.IP) (string, error) { + dns, ok := o.DNSPtr[ip.String()] if !ok { return "", DNSNotFoundError{ip} } @@ -84,7 +92,7 @@ // FloatingIPClient is a client for the Floating IP API. type FloatingIPClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*FloatingIP] } // GetByID retrieves a Floating IP by its ID. If the Floating IP does not exist, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go 2026-01-16 15:53:42.000000000 +0100 @@ -24,6 +24,7 @@ When the API returned an application error, with the code: - [ErrorCodeConflict] - [ErrorCodeRateLimitExceeded] + - [ErrorCodeTimeout] Changes to the retry policy might occur between releases, and will not be considered breaking changes. @@ -31,4 +32,4 @@ package hcloud // Version is the library's version following Semantic Versioning. -const Version = "2.33.0" // x-releaser-pleaser-version +const Version = "2.35.0" // x-releaser-pleaser-version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go 2026-01-16 15:53:42.000000000 +0100 @@ -35,14 +35,21 @@ Deleted time.Time } +func (o *Image) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // IsDeprecated returns whether the image is deprecated. -func (image *Image) IsDeprecated() bool { - return !image.Deprecated.IsZero() +func (o *Image) IsDeprecated() bool { + return !o.Deprecated.IsZero() } // IsDeleted returns whether the image is deleted. -func (image *Image) IsDeleted() bool { - return !image.Deleted.IsZero() +func (o *Image) IsDeleted() bool { + return !o.Deleted.IsZero() } // ImageProtection represents the protection level of an image. @@ -77,7 +84,7 @@ // ImageClient is a client for the image API. type ImageClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Image] } // GetByID retrieves an image by its ID. If the image does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go 2026-01-16 15:53:42.000000000 +0100 @@ -32,6 +32,13 @@ IngoingTraffic uint64 } +func (o *LoadBalancer) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // LoadBalancerPublicNet represents a Load Balancer's public network. type LoadBalancerPublicNet struct { Enabled bool @@ -198,11 +205,11 @@ // changeDNSPtr changes or resets the reverse DNS pointer for an IP address. // Pass a nil ptr to reset the reverse DNS pointer to its default value. -func (lb *LoadBalancer) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { +func (o *LoadBalancer) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { const opPath = "/load_balancers/%d/actions/change_dns_ptr" ctx = ctxutil.SetOpPath(ctx, opPath) - reqPath := fmt.Sprintf(opPath, lb.ID) + reqPath := fmt.Sprintf(opPath, o.ID) reqBody := schema.LoadBalancerActionChangeDNSPtrRequest{ IP: ip.String(), @@ -219,11 +226,11 @@ // GetDNSPtrForIP searches for the dns assigned to the given IP address. // It returns an error if there is no dns set for the given IP address. -func (lb *LoadBalancer) GetDNSPtrForIP(ip net.IP) (string, error) { - if net.IP.Equal(lb.PublicNet.IPv4.IP, ip) { - return lb.PublicNet.IPv4.DNSPtr, nil - } else if net.IP.Equal(lb.PublicNet.IPv6.IP, ip) { - return lb.PublicNet.IPv6.DNSPtr, nil +func (o *LoadBalancer) GetDNSPtrForIP(ip net.IP) (string, error) { + if net.IP.Equal(o.PublicNet.IPv4.IP, ip) { + return o.PublicNet.IPv4.DNSPtr, nil + } else if net.IP.Equal(o.PublicNet.IPv6.IP, ip) { + return o.PublicNet.IPv6.DNSPtr, nil } return "", DNSNotFoundError{ip} @@ -231,20 +238,20 @@ // PrivateNetFor returns the load balancer's network attachment information in the given // Network, and nil if no attachment was found. -func (lb *LoadBalancer) PrivateNetFor(network *Network) *LoadBalancerPrivateNet { - index := slices.IndexFunc(lb.PrivateNet, func(o LoadBalancerPrivateNet) bool { - return o.Network != nil && o.Network.ID == network.ID +func (o *LoadBalancer) PrivateNetFor(network *Network) *LoadBalancerPrivateNet { + index := slices.IndexFunc(o.PrivateNet, func(n LoadBalancerPrivateNet) bool { + return n.Network != nil && n.Network.ID == network.ID }) if index < 0 { return nil } - return &lb.PrivateNet[index] + return &o.PrivateNet[index] } // LoadBalancerClient is a client for the Load Balancers API. type LoadBalancerClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*LoadBalancer] } // GetByID retrieves a Load Balancer by its ID. If the Load Balancer does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go 2026-01-16 15:53:42.000000000 +0100 @@ -5,6 +5,7 @@ "fmt" "net" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -56,6 +57,13 @@ ExposeRoutesToVSwitch bool } +func (o *Network) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // NetworkSubnet represents a subnet of a network in the Hetzner Cloud. type NetworkSubnet struct { Type NetworkSubnetType @@ -79,7 +87,7 @@ // NetworkClient is a client for the network API. type NetworkClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Network] } // GetByID retrieves a network by its ID. If the network does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go 2026-01-16 15:53:42.000000000 +0100 @@ -5,6 +5,7 @@ "fmt" "net" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -34,6 +35,13 @@ Datacenter *Datacenter } +func (o *PrimaryIP) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // PrimaryIPProtection represents the protection level of a Primary IP. type PrimaryIPProtection struct { Delete bool @@ -48,11 +56,11 @@ // 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. -func (p *PrimaryIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { +func (o *PrimaryIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { const opPath = "/primary_ips/%d/actions/change_dns_ptr" ctx = ctxutil.SetOpPath(ctx, opPath) - reqPath := fmt.Sprintf(opPath, p.ID) + reqPath := fmt.Sprintf(opPath, o.ID) reqBody := schema.PrimaryIPActionChangeDNSPtrRequest{ IP: ip.String(), @@ -69,8 +77,8 @@ // GetDNSPtrForIP searches for the dns assigned to the given IP address. // It returns an error if there is no dns set for the given IP address. -func (p *PrimaryIP) GetDNSPtrForIP(ip net.IP) (string, error) { - dns, ok := p.DNSPtr[ip.String()] +func (o *PrimaryIP) GetDNSPtrForIP(ip net.IP) (string, error) { + dns, ok := o.DNSPtr[ip.String()] if !ok { return "", DNSNotFoundError{ip} } @@ -154,7 +162,7 @@ // PrimaryIPClient is a client for the Primary IP API. type PrimaryIPClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*PrimaryIP] } // GetByID retrieves a Primary IP by its ID. If the Primary IP does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/storage_box_subaccount.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/storage_box_subaccount.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/storage_box_subaccount.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/storage_box_subaccount.go 2026-01-16 15:53:42.000000000 +0100 @@ -5,6 +5,7 @@ // StorageBoxSubaccount defines the schema of a Storage Box subaccount. type StorageBoxSubaccount struct { ID int64 `json:"id"` + Name string `json:"name"` Username string `json:"username"` HomeDirectory string `json:"home_directory"` Server string `json:"server"` @@ -36,6 +37,7 @@ // StorageBoxSubaccountCreateRequest defines the schema of the request when creating a Storage Box subaccount. type StorageBoxSubaccountCreateRequest struct { + Name string `json:"name,omitempty"` HomeDirectory string `json:"home_directory"` Password string `json:"password"` Description string `json:"description,omitempty"` @@ -68,6 +70,7 @@ // StorageBoxSubaccountUpdateRequest defines the schema of the request when updating a Storage Box subaccount. type StorageBoxSubaccountUpdateRequest struct { + Name string `json:"name,omitempty"` Description *string `json:"description,omitempty"` Labels *map[string]string `json:"labels,omitempty"` } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go 2026-01-16 15:53:42.000000000 +0100 @@ -44,6 +44,13 @@ Datacenter *Datacenter } +func (o *Server) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // ServerProtection represents the protection level of a server. type ServerProtection struct { Delete, Rebuild bool @@ -108,8 +115,8 @@ DNSPtr string } -func (n *ServerPublicNetIPv4) IsUnspecified() bool { - return n.IP == nil || n.IP.Equal(net.IPv4zero) +func (o *ServerPublicNetIPv4) IsUnspecified() bool { + return o.IP == nil || o.IP.Equal(net.IPv4zero) } // ServerPublicNetIPv6 represents a Server's public IPv6 network and address. @@ -121,8 +128,8 @@ DNSPtr map[string]string } -func (n *ServerPublicNetIPv6) IsUnspecified() bool { - return n.IP == nil || n.IP.Equal(net.IPv6unspecified) +func (o *ServerPublicNetIPv6) IsUnspecified() bool { + return o.IP == nil || o.IP.Equal(net.IPv6unspecified) } // ServerPrivateNet defines the schema of a Server's private network information. @@ -134,8 +141,8 @@ } // DNSPtrForIP returns the reverse dns pointer of the ip address. -func (n *ServerPublicNetIPv6) DNSPtrForIP(ip net.IP) string { - return n.DNSPtr[ip.String()] +func (o *ServerPublicNetIPv6) DNSPtrForIP(ip net.IP) string { + return o.DNSPtr[ip.String()] } // ServerFirewallStatus represents a Firewall and its status on a Server's @@ -157,11 +164,11 @@ // 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. -func (s *Server) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { +func (o *Server) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { const opPath = "/servers/%d/actions/change_dns_ptr" ctx = ctxutil.SetOpPath(ctx, opPath) - reqPath := fmt.Sprintf(opPath, s.ID) + reqPath := fmt.Sprintf(opPath, o.ID) reqBody := schema.ServerActionChangeDNSPtrRequest{ IP: ip.String(), @@ -178,10 +185,10 @@ // GetDNSPtrForIP searches for the dns assigned to the given IP address. // It returns an error if there is no dns set for the given IP address. -func (s *Server) GetDNSPtrForIP(ip net.IP) (string, error) { - if net.IP.Equal(s.PublicNet.IPv4.IP, ip) { - return s.PublicNet.IPv4.DNSPtr, nil - } else if dns, ok := s.PublicNet.IPv6.DNSPtr[ip.String()]; ok { +func (o *Server) GetDNSPtrForIP(ip net.IP) (string, error) { + if net.IP.Equal(o.PublicNet.IPv4.IP, ip) { + return o.PublicNet.IPv4.DNSPtr, nil + } else if dns, ok := o.PublicNet.IPv6.DNSPtr[ip.String()]; ok { return dns, nil } @@ -190,20 +197,20 @@ // PrivateNetFor returns the server's network attachment information in the given // Network, and nil if no attachment was found. -func (s *Server) PrivateNetFor(network *Network) *ServerPrivateNet { - index := slices.IndexFunc(s.PrivateNet, func(o ServerPrivateNet) bool { - return o.Network != nil && o.Network.ID == network.ID +func (o *Server) PrivateNetFor(network *Network) *ServerPrivateNet { + index := slices.IndexFunc(o.PrivateNet, func(n ServerPrivateNet) bool { + return n.Network != nil && n.Network.ID == network.ID }) if index < 0 { return nil } - return &s.PrivateNet[index] + return &o.PrivateNet[index] } // ServerClient is a client for the servers API. type ServerClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Server] } // GetByID retrieves a server by its ID. If the server does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box.go 2026-01-16 15:53:42.000000000 +0100 @@ -4,6 +4,7 @@ "context" "fmt" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -30,6 +31,13 @@ Created time.Time } +func (o *StorageBox) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + // StorageBoxAccessSettings represents the access settings of a [StorageBox]. type StorageBoxAccessSettings struct { ReachableExternally bool @@ -87,7 +95,7 @@ // Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. type StorageBoxClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*StorageBox] } // GetByID retrieves a [StorageBox] by its ID. If the [StorageBox] does not exist, nil is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box_subaccount.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box_subaccount.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box_subaccount.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/storage_box_subaccount.go 2026-01-16 15:53:42.000000000 +0100 @@ -15,6 +15,7 @@ // See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts type StorageBoxSubaccount struct { ID int64 + Name string Username string HomeDirectory string Server string @@ -34,7 +35,7 @@ WebDAVEnabled bool } -// GetSubaccount retrieves a [StorageBoxSubaccount] either by its ID or by its username, depending on whether +// GetSubaccount retrieves a [StorageBoxSubaccount] either by its ID or by its name, depending on whether // the input can be parsed as an integer. If no matching [StorageBoxSubaccount] is found, it returns nil. // // When fetching by ID, see https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-get-a-subaccount @@ -44,17 +45,17 @@ func (c *StorageBoxClient) GetSubaccount( ctx context.Context, storageBox *StorageBox, - idOrUsername string, + idOrName string, ) (*StorageBoxSubaccount, *Response, error) { return getByIDOrName( ctx, func(ctx context.Context, id int64) (*StorageBoxSubaccount, *Response, error) { return c.GetSubaccountByID(ctx, storageBox, id) }, - func(ctx context.Context, username string) (*StorageBoxSubaccount, *Response, error) { - return c.GetSubaccountByUsername(ctx, storageBox, username) + func(ctx context.Context, name string) (*StorageBoxSubaccount, *Response, error) { + return c.GetSubaccountByName(ctx, storageBox, name) }, - idOrUsername, + idOrName, ) } @@ -84,6 +85,23 @@ return StorageBoxSubaccountFromSchema(respBody.Subaccount), resp, nil } +// GetSubaccountByName retrieves a [StorageBoxSubaccount] by its name. +// +// See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts +// +// Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. +func (c *StorageBoxClient) GetSubaccountByName( + ctx context.Context, + storageBox *StorageBox, + name string, +) (*StorageBoxSubaccount, *Response, error) { + return firstByName(name, func() ([]*StorageBoxSubaccount, *Response, error) { + return c.ListSubaccounts(ctx, storageBox, StorageBoxSubaccountListOpts{ + Name: name, + }) + }) +} + // GetSubaccountByUsername retrieves a [StorageBoxSubaccount] by its username. // // See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts @@ -104,12 +122,16 @@ // StorageBoxSubaccountListOpts represents the options for listing [StorageBoxSubaccount]. type StorageBoxSubaccountListOpts struct { LabelSelector string + Name string Username string Sort []string } func (o StorageBoxSubaccountListOpts) values() url.Values { vals := url.Values{} + if o.Name != "" { + vals.Add("name", o.Name) + } if o.Username != "" { vals.Add("username", o.Username) } @@ -175,6 +197,7 @@ // StorageBoxSubaccountCreateOpts represents the options for creating a [StorageBoxSubaccount]. type StorageBoxSubaccountCreateOpts struct { + Name string HomeDirectory string Password string Description string @@ -228,6 +251,7 @@ // StorageBoxSubaccountUpdateOpts represents the options for updating a [StorageBoxSubaccount]. type StorageBoxSubaccountUpdateOpts struct { + Name string Description *string Labels map[string]string } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go 2026-01-16 15:53:42.000000000 +0100 @@ -4,6 +4,7 @@ "context" "fmt" "net/url" + "strconv" "time" "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/ctxutil" @@ -25,6 +26,13 @@ Created time.Time } +func (o *Volume) pathID() (string, error) { + if o.ID == 0 { + return "", missingField(o, "ID") + } + return strconv.FormatInt(o.ID, 10), nil +} + const ( VolumeFormatExt4 = "ext4" VolumeFormatXFS = "xfs" @@ -38,7 +46,7 @@ // VolumeClient is a client for the volume API. type VolumeClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Volume] } // VolumeStatus specifies a volume's status. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zone.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zone.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zone.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zone.go 2026-01-16 15:53:42.000000000 +0100 @@ -108,13 +108,17 @@ } } +func (o *Zone) pathID() (string, error) { + return o.idOrName() +} + // ZoneClient is a client for the Zone (DNS) API. // // See https://docs.hetzner.cloud/reference/cloud#zones and // https://docs.hetzner.cloud/reference/cloud#zone-rrsets. type ZoneClient struct { client *Client - Action *ResourceActionClient + Action *ResourceActionClient[*Zone] } // GetByID returns a single [Zone]. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go 2026-01-16 15:53:42.000000000 +0100 @@ -10,7 +10,7 @@ type IActionClient interface { // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. GetByID(ctx context.Context, id int64) (*Action, *Response, error) - // List returns a list of actions for a specific page. + // List returns a paginated list of actions. // // Please note that filters specified in opts are not taken into account // when their value corresponds to their zero value or when they are empty. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go 2026-01-16 15:53:42.000000000 +0100 @@ -7,14 +7,21 @@ ) // IResourceActionClient ... -type IResourceActionClient interface { +type IResourceActionClient[R actionSupporter] interface { // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. GetByID(ctx context.Context, id int64) (*Action, *Response, error) - // List returns a list of actions for a specific page. + // List returns a paginated list of actions. // // Please note that filters specified in opts are not taken into account // when their value corresponds to their zero value or when they are empty. List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) // All returns all actions for the given options. All(ctx context.Context, opts ActionListOpts) ([]*Action, error) + // ListFor returns a paginated list of actions for the given Resource. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + ListFor(ctx context.Context, resource R, opts ActionListOpts) ([]*Action, *Response, error) + // AllFor returns all actions for the given Resource. + AllFor(ctx context.Context, resource R, opts ActionListOpts) ([]*Action, error) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go 2026-01-16 15:53:42.000000000 +0100 @@ -1226,6 +1226,7 @@ var schemaStorageBoxSubaccount schema.StorageBoxSubaccount if source != nil { schemaStorageBoxSubaccount.ID = (*source).ID + schemaStorageBoxSubaccount.Name = (*source).Name schemaStorageBoxSubaccount.Username = (*source).Username schemaStorageBoxSubaccount.HomeDirectory = (*source).HomeDirectory schemaStorageBoxSubaccount.Server = (*source).Server @@ -1244,6 +1245,7 @@ } func (c *converterImpl) SchemaFromStorageBoxSubaccountCreateOpts(source StorageBoxSubaccountCreateOpts) schema.StorageBoxSubaccountCreateRequest { var schemaStorageBoxSubaccountCreateRequest schema.StorageBoxSubaccountCreateRequest + schemaStorageBoxSubaccountCreateRequest.Name = source.Name schemaStorageBoxSubaccountCreateRequest.HomeDirectory = source.HomeDirectory schemaStorageBoxSubaccountCreateRequest.Password = source.Password schemaStorageBoxSubaccountCreateRequest.Description = source.Description @@ -1267,6 +1269,7 @@ } func (c *converterImpl) SchemaFromStorageBoxSubaccountUpdateOpts(source StorageBoxSubaccountUpdateOpts) schema.StorageBoxSubaccountUpdateRequest { var schemaStorageBoxSubaccountUpdateRequest schema.StorageBoxSubaccountUpdateRequest + schemaStorageBoxSubaccountUpdateRequest.Name = source.Name schemaStorageBoxSubaccountUpdateRequest.Description = source.Description schemaStorageBoxSubaccountUpdateRequest.Labels = stringMapToStringMapPtr(source.Labels) return schemaStorageBoxSubaccountUpdateRequest @@ -1687,6 +1690,7 @@ func (c *converterImpl) StorageBoxSubaccountFromSchema(source schema.StorageBoxSubaccount) *StorageBoxSubaccount { var hcloudStorageBoxSubaccount StorageBoxSubaccount hcloudStorageBoxSubaccount.ID = source.ID + hcloudStorageBoxSubaccount.Name = source.Name hcloudStorageBoxSubaccount.Username = source.Username hcloudStorageBoxSubaccount.HomeDirectory = source.HomeDirectory hcloudStorageBoxSubaccount.Server = source.Server diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_storage_box_client_iface.go new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_storage_box_client_iface.go --- old/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_storage_box_client_iface.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_storage_box_client_iface.go 2026-01-16 15:53:42.000000000 +0100 @@ -177,20 +177,26 @@ // // Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. DeleteSnapshot(ctx context.Context, snapshot *StorageBoxSnapshot) (StorageBoxSnapshotDeleteResult, *Response, error) - // GetSubaccount retrieves a [StorageBoxSubaccount] either by its ID or by its username, depending on whether + // GetSubaccount retrieves a [StorageBoxSubaccount] either by its ID or by its name, depending on whether // the input can be parsed as an integer. If no matching [StorageBoxSubaccount] is found, it returns nil. // // When fetching by ID, see https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-get-a-subaccount // When fetching by name, see https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts // // Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. - GetSubaccount(ctx context.Context, storageBox *StorageBox, idOrUsername string) (*StorageBoxSubaccount, *Response, error) + GetSubaccount(ctx context.Context, storageBox *StorageBox, idOrName string) (*StorageBoxSubaccount, *Response, error) // GetSubaccountByID retrieves a [StorageBoxSubaccount] by its ID. // // See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-get-a-subaccount // // Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. GetSubaccountByID(ctx context.Context, storageBox *StorageBox, id int64) (*StorageBoxSubaccount, *Response, error) + // GetSubaccountByName retrieves a [StorageBoxSubaccount] by its name. + // + // See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts + // + // Experimental: [StorageBoxClient] is experimental, breaking changes may occur within minor releases. + GetSubaccountByName(ctx context.Context, storageBox *StorageBox, name string) (*StorageBoxSubaccount, *Response, error) // GetSubaccountByUsername retrieves a [StorageBoxSubaccount] by its username. // // See https://docs.hetzner.cloud/reference/hetzner#storage-box-subaccounts-list-subaccounts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/golang.org/x/sys/cpu/cpu_x86.go new/vendor/golang.org/x/sys/cpu/cpu_x86.go --- old/vendor/golang.org/x/sys/cpu/cpu_x86.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/golang.org/x/sys/cpu/cpu_x86.go 2026-01-16 15:53:42.000000000 +0100 @@ -64,6 +64,80 @@ func archInit() { + // From internal/cpu + const ( + // eax bits + cpuid_AVXVNNI = 1 << 4 + + // ecx bits + cpuid_SSE3 = 1 << 0 + cpuid_PCLMULQDQ = 1 << 1 + cpuid_AVX512VBMI = 1 << 1 + cpuid_AVX512VBMI2 = 1 << 6 + cpuid_SSSE3 = 1 << 9 + cpuid_AVX512GFNI = 1 << 8 + cpuid_AVX512VAES = 1 << 9 + cpuid_AVX512VNNI = 1 << 11 + cpuid_AVX512BITALG = 1 << 12 + cpuid_FMA = 1 << 12 + cpuid_AVX512VPOPCNTDQ = 1 << 14 + cpuid_SSE41 = 1 << 19 + cpuid_SSE42 = 1 << 20 + cpuid_POPCNT = 1 << 23 + cpuid_AES = 1 << 25 + cpuid_OSXSAVE = 1 << 27 + cpuid_AVX = 1 << 28 + + // "Extended Feature Flag" bits returned in EBX for CPUID EAX=0x7 ECX=0x0 + cpuid_BMI1 = 1 << 3 + cpuid_AVX2 = 1 << 5 + cpuid_BMI2 = 1 << 8 + cpuid_ERMS = 1 << 9 + cpuid_AVX512F = 1 << 16 + cpuid_AVX512DQ = 1 << 17 + cpuid_ADX = 1 << 19 + cpuid_AVX512CD = 1 << 28 + cpuid_SHA = 1 << 29 + cpuid_AVX512BW = 1 << 30 + cpuid_AVX512VL = 1 << 31 + + // "Extended Feature Flag" bits returned in ECX for CPUID EAX=0x7 ECX=0x0 + cpuid_AVX512_VBMI = 1 << 1 + cpuid_AVX512_VBMI2 = 1 << 6 + cpuid_GFNI = 1 << 8 + cpuid_AVX512VPCLMULQDQ = 1 << 10 + cpuid_AVX512_BITALG = 1 << 12 + + // edx bits + cpuid_FSRM = 1 << 4 + // edx bits for CPUID 0x80000001 + cpuid_RDTSCP = 1 << 27 + ) + // Additional constants not in internal/cpu + const ( + // eax=1: edx + cpuid_SSE2 = 1 << 26 + // eax=1: ecx + cpuid_CX16 = 1 << 13 + cpuid_RDRAND = 1 << 30 + // eax=7,ecx=0: ebx + cpuid_RDSEED = 1 << 18 + cpuid_AVX512IFMA = 1 << 21 + cpuid_AVX512PF = 1 << 26 + cpuid_AVX512ER = 1 << 27 + // eax=7,ecx=0: edx + cpuid_AVX5124VNNIW = 1 << 2 + cpuid_AVX5124FMAPS = 1 << 3 + cpuid_AMXBF16 = 1 << 22 + cpuid_AMXTile = 1 << 24 + cpuid_AMXInt8 = 1 << 25 + // eax=7,ecx=1: eax + cpuid_AVX512BF16 = 1 << 5 + cpuid_AVXIFMA = 1 << 23 + // eax=7,ecx=1: edx + cpuid_AVXVNNIInt8 = 1 << 4 + ) + Initialized = true maxID, _, _, _ := cpuid(0, 0) @@ -73,90 +147,90 @@ } _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(26, edx1) + X86.HasSSE2 = isSet(edx1, cpuid_SSE2) - X86.HasSSE3 = isSet(0, ecx1) - X86.HasPCLMULQDQ = isSet(1, ecx1) - X86.HasSSSE3 = isSet(9, ecx1) - X86.HasFMA = isSet(12, ecx1) - X86.HasCX16 = isSet(13, ecx1) - X86.HasSSE41 = isSet(19, ecx1) - X86.HasSSE42 = isSet(20, ecx1) - X86.HasPOPCNT = isSet(23, ecx1) - X86.HasAES = isSet(25, ecx1) - X86.HasOSXSAVE = isSet(27, ecx1) - X86.HasRDRAND = isSet(30, ecx1) + X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) + X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) + X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3) + X86.HasFMA = isSet(ecx1, cpuid_FMA) + X86.HasCX16 = isSet(ecx1, cpuid_CX16) + X86.HasSSE41 = isSet(ecx1, cpuid_SSE41) + X86.HasSSE42 = isSet(ecx1, cpuid_SSE42) + X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT) + X86.HasAES = isSet(ecx1, cpuid_AES) + X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) + X86.HasRDRAND = isSet(ecx1, cpuid_RDRAND) var osSupportsAVX, osSupportsAVX512 bool // For XGETBV, OSXSAVE bit is required and sufficient. if X86.HasOSXSAVE { eax, _ := xgetbv() // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) + osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2) if runtime.GOOS == "darwin" { // Darwin requires special AVX512 checks, see cpu_darwin_x86.go osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() } else { // Check if OPMASK and ZMM registers have OS support. - osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) + osSupportsAVX512 = osSupportsAVX && isSet(eax, 1<<5) && isSet(eax, 1<<6) && isSet(eax, 1<<7) } } - X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX if maxID < 7 { return } eax7, ebx7, ecx7, edx7 := cpuid(7, 0) - X86.HasBMI1 = isSet(3, ebx7) - X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX - X86.HasBMI2 = isSet(8, ebx7) - X86.HasERMS = isSet(9, ebx7) - X86.HasRDSEED = isSet(18, ebx7) - X86.HasADX = isSet(19, ebx7) + X86.HasBMI1 = isSet(ebx7, cpuid_BMI1) + X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX + X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) + X86.HasERMS = isSet(ebx7, cpuid_ERMS) + X86.HasRDSEED = isSet(ebx7, cpuid_RDSEED) + X86.HasADX = isSet(ebx7, cpuid_ADX) - X86.HasAVX512 = isSet(16, ebx7) && osSupportsAVX512 // Because avx-512 foundation is the core required extension + X86.HasAVX512 = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 // Because avx-512 foundation is the core required extension if X86.HasAVX512 { X86.HasAVX512F = true - X86.HasAVX512CD = isSet(28, ebx7) - X86.HasAVX512ER = isSet(27, ebx7) - X86.HasAVX512PF = isSet(26, ebx7) - X86.HasAVX512VL = isSet(31, ebx7) - X86.HasAVX512BW = isSet(30, ebx7) - X86.HasAVX512DQ = isSet(17, ebx7) - X86.HasAVX512IFMA = isSet(21, ebx7) - X86.HasAVX512VBMI = isSet(1, ecx7) - X86.HasAVX5124VNNIW = isSet(2, edx7) - X86.HasAVX5124FMAPS = isSet(3, edx7) - X86.HasAVX512VPOPCNTDQ = isSet(14, ecx7) - X86.HasAVX512VPCLMULQDQ = isSet(10, ecx7) - X86.HasAVX512VNNI = isSet(11, ecx7) - X86.HasAVX512GFNI = isSet(8, ecx7) - X86.HasAVX512VAES = isSet(9, ecx7) - X86.HasAVX512VBMI2 = isSet(6, ecx7) - X86.HasAVX512BITALG = isSet(12, ecx7) + X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD) + X86.HasAVX512ER = isSet(ebx7, cpuid_AVX512ER) + X86.HasAVX512PF = isSet(ebx7, cpuid_AVX512PF) + X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) + X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) + X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ) + X86.HasAVX512IFMA = isSet(ebx7, cpuid_AVX512IFMA) + X86.HasAVX512VBMI = isSet(ecx7, cpuid_AVX512_VBMI) + X86.HasAVX5124VNNIW = isSet(edx7, cpuid_AVX5124VNNIW) + X86.HasAVX5124FMAPS = isSet(edx7, cpuid_AVX5124FMAPS) + X86.HasAVX512VPOPCNTDQ = isSet(ecx7, cpuid_AVX512VPOPCNTDQ) + X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) + X86.HasAVX512VNNI = isSet(ecx7, cpuid_AVX512VNNI) + X86.HasAVX512GFNI = isSet(ecx7, cpuid_AVX512GFNI) + X86.HasAVX512VAES = isSet(ecx7, cpuid_AVX512VAES) + X86.HasAVX512VBMI2 = isSet(ecx7, cpuid_AVX512VBMI2) + X86.HasAVX512BITALG = isSet(ecx7, cpuid_AVX512BITALG) } - X86.HasAMXTile = isSet(24, edx7) - X86.HasAMXInt8 = isSet(25, edx7) - X86.HasAMXBF16 = isSet(22, edx7) + X86.HasAMXTile = isSet(edx7, cpuid_AMXTile) + X86.HasAMXInt8 = isSet(edx7, cpuid_AMXInt8) + X86.HasAMXBF16 = isSet(edx7, cpuid_AMXBF16) // These features depend on the second level of extended features. if eax7 >= 1 { eax71, _, _, edx71 := cpuid(7, 1) if X86.HasAVX512 { - X86.HasAVX512BF16 = isSet(5, eax71) + X86.HasAVX512BF16 = isSet(eax71, cpuid_AVX512BF16) } if X86.HasAVX { - X86.HasAVXIFMA = isSet(23, eax71) - X86.HasAVXVNNI = isSet(4, eax71) - X86.HasAVXVNNIInt8 = isSet(4, edx71) + X86.HasAVXIFMA = isSet(eax71, cpuid_AVXIFMA) + X86.HasAVXVNNI = isSet(eax71, cpuid_AVXVNNI) + X86.HasAVXVNNIInt8 = isSet(edx71, cpuid_AVXVNNIInt8) } } } -func isSet(bitpos uint, value uint32) bool { - return value&(1<<bitpos) != 0 +func isSet(hwc uint32, value uint32) bool { + return hwc&value != 0 } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/golang.org/x/term/terminal.go new/vendor/golang.org/x/term/terminal.go --- old/vendor/golang.org/x/term/terminal.go 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/golang.org/x/term/terminal.go 2026-01-16 15:53:42.000000000 +0100 @@ -160,7 +160,9 @@ keyEnd keyDeleteWord keyDeleteLine + keyDelete keyClearScreen + keyTranspose keyPasteStart keyPasteEnd ) @@ -194,6 +196,8 @@ return keyDeleteLine, b[1:] case 12: // ^L return keyClearScreen, b[1:] + case 20: // ^T + return keyTranspose, b[1:] case 23: // ^W return keyDeleteWord, b[1:] case 14: // ^N @@ -228,6 +232,10 @@ } } + if !pasteActive && len(b) >= 4 && b[0] == keyEscape && b[1] == '[' && b[2] == '3' && b[3] == '~' { + return keyDelete, b[4:] + } + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { switch b[5] { case 'C': @@ -590,7 +598,7 @@ } t.line = t.line[:t.pos] t.moveCursorToPos(t.pos) - case keyCtrlD: + case keyCtrlD, keyDelete: // Erase the character under the current position. // The EOF case when the line is empty is handled in // readLine(). @@ -600,6 +608,24 @@ } case keyCtrlU: t.eraseNPreviousChars(t.pos) + case keyTranspose: + // This transposes the two characters around the cursor and advances the cursor. Best-effort. + if len(t.line) < 2 || t.pos < 1 { + return + } + swap := t.pos + if swap == len(t.line) { + swap-- // special: at end of line, swap previous two chars + } + t.line[swap-1], t.line[swap] = t.line[swap], t.line[swap-1] + if t.pos < len(t.line) { + t.pos++ + } + if t.echo { + t.moveCursorToPos(swap - 1) + t.writeLine(t.line[swap-1:]) + t.moveCursorToPos(t.pos) + } case keyClearScreen: // Erases the screen and moves the cursor to the home position. t.queue([]rune("\x1b[2J\x1b[H")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2026-01-05 17:16:10.000000000 +0100 +++ new/vendor/modules.txt 2026-01-16 15:53:42.000000000 +0100 @@ -41,7 +41,7 @@ ## explicit; go 1.18 github.com/go-viper/mapstructure/v2 github.com/go-viper/mapstructure/v2/internal/errors -# github.com/goccy/go-yaml v1.19.1 +# github.com/goccy/go-yaml v1.19.2 ## explicit; go 1.21.0 github.com/goccy/go-yaml github.com/goccy/go-yaml/ast @@ -55,7 +55,7 @@ # github.com/guptarohit/asciigraph v0.7.3 ## explicit; go 1.11 github.com/guptarohit/asciigraph -# github.com/hetznercloud/hcloud-go/v2 v2.33.0 +# github.com/hetznercloud/hcloud-go/v2 v2.35.0 ## explicit; go 1.24.0 github.com/hetznercloud/hcloud-go/v2/hcloud github.com/hetznercloud/hcloud-go/v2/hcloud/exp/actionutil @@ -184,7 +184,7 @@ # go.yaml.in/yaml/v3 v3.0.4 ## explicit; go 1.16 go.yaml.in/yaml/v3 -# golang.org/x/crypto v0.46.0 +# golang.org/x/crypto v0.47.0 ## explicit; go 1.24.0 golang.org/x/crypto/blowfish golang.org/x/crypto/chacha20 @@ -193,23 +193,23 @@ golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/ssh golang.org/x/crypto/ssh/internal/bcrypt_pbkdf -# golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 +# golang.org/x/exp v0.0.0-20260112195511-716be5621a96 ## explicit; go 1.24.0 golang.org/x/exp/maps -# golang.org/x/net v0.48.0 +# golang.org/x/net v0.49.0 ## explicit; go 1.24.0 golang.org/x/net/http/httpguts golang.org/x/net/idna -# golang.org/x/sys v0.39.0 +# golang.org/x/sys v0.40.0 ## explicit; go 1.24.0 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.38.0 +# golang.org/x/term v0.39.0 ## explicit; go 1.24.0 golang.org/x/term -# golang.org/x/text v0.32.0 +# golang.org/x/text v0.33.0 ## explicit; go 1.24.0 golang.org/x/text/cases golang.org/x/text/encoding
