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 2025-09-26 22:24:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hcloud-cli (Old) and /work/SRC/openSUSE:Factory/.hcloud-cli.new.11973 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hcloud-cli" Fri Sep 26 22:24:48 2025 rev:7 rq:1307257 version:1.53.0 Changes: -------- --- /work/SRC/openSUSE:Factory/hcloud-cli/hcloud-cli.changes 2025-09-18 21:11:49.030319988 +0200 +++ /work/SRC/openSUSE:Factory/.hcloud-cli.new.11973/hcloud-cli.changes 2025-09-26 22:26:16.082426219 +0200 @@ -1,0 +2,26 @@ +Fri Sep 26 05:31:11 UTC 2025 - Johannes Kastl <[email protected]> + +- Update to version 1.53.0: + Server Types now depend on Locations. + We added a new locations property to the Server Types resource. + The new property defines a list of supported Locations and + additional per Locations details such as deprecations + information. + We deprecated the deprecation property from the Server Types + resource. The property will gradually be phased out as per + Locations deprecations are being announced. Please use the new + per Locations deprecation information instead. + * Features + - add category property to server type (#1150) + - per location server types (#1166) + * Dependencies + - deps: update module github.com/hetznercloud/hcloud-go/v2 to + v2.25.0 (#1168) + - deps: update module github.com/hetznercloud/hcloud-go/v2 to + v2.24.0 (#1162) + - deps: update module github.com/spf13/viper to v1.21.0 (#1156) + - deps: update module golang.org/x/crypto to v0.42.0 (#1154) + - deps: update module github.com/hetznercloud/hcloud-go/v2 to + v2.23.0 (#1149) + +------------------------------------------------------------------- Old: ---- hcloud-cli-1.52.0.obscpio New: ---- hcloud-cli-1.53.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hcloud-cli.spec ++++++ --- /var/tmp/diff_new_pack.r3Dub9/_old 2025-09-26 22:26:16.766455068 +0200 +++ /var/tmp/diff_new_pack.r3Dub9/_new 2025-09-26 22:26:16.770455236 +0200 @@ -19,7 +19,7 @@ %define executable_name hcloud Name: hcloud-cli -Version: 1.52.0 +Version: 1.53.0 Release: 0 Summary: A command-line interface for Hetzner Cloud License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.r3Dub9/_old 2025-09-26 22:26:16.802456586 +0200 +++ /var/tmp/diff_new_pack.r3Dub9/_new 2025-09-26 22:26:16.806456755 +0200 @@ -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.52.0</param> + <param name="revision">v1.53.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.r3Dub9/_old 2025-09-26 22:26:16.838458104 +0200 +++ /var/tmp/diff_new_pack.r3Dub9/_new 2025-09-26 22:26:16.842458273 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/hetznercloud/cli</param> - <param name="changesrevision">6dec460911978e46fdf9127e3c6b411c722efe89</param></service></servicedata> + <param name="changesrevision">29f8f3b2f5f60c9b16b44abb980467a043d5891e</param></service></servicedata> (No newline at EOF) ++++++ hcloud-cli-1.52.0.obscpio -> hcloud-cli-1.53.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/CHANGELOG.md new/hcloud-cli-1.53.0/CHANGELOG.md --- old/hcloud-cli-1.52.0/CHANGELOG.md 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/CHANGELOG.md 2025-09-25 15:00:37.000000000 +0200 @@ -1,5 +1,20 @@ # Changelog +## [v1.53.0](https://github.com/hetznercloud/cli/releases/tag/v1.53.0) + +[Server Types](https://docs.hetzner.cloud/reference/cloud#server-types) now depend on [Locations](https://docs.hetzner.cloud/reference/cloud#locations). + +- We added a new `locations` property to the [Server Types](https://docs.hetzner.cloud/reference/cloud#server-types) resource. The new property defines a list of supported [Locations](https://docs.hetzner.cloud/reference/cloud#locations) and additional per [Locations](https://docs.hetzner.cloud/reference/cloud#locations) details such as deprecations information. + +- We deprecated the `deprecation` property from the [Server Types](https://docs.hetzner.cloud/reference/cloud#server-types) resource. The property will gradually be phased out as per [Locations](https://docs.hetzner.cloud/reference/cloud#locations) deprecations are being announced. Please use the new per [Locations](https://docs.hetzner.cloud/reference/cloud#locations) deprecation information instead. + +See our [changelog](https://docs.hetzner.cloud/changelog#2025-09-24-per-location-server-types) for more details. + +### Features + +- add category property to server type (#1150) +- per location server types (#1166) + ## [v1.52.0](https://github.com/hetznercloud/cli/releases/tag/v1.52.0) ### Features diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/docs/reference/manual/hcloud_server-type_list.md new/hcloud-cli-1.53.0/docs/reference/manual/hcloud_server-type_list.md --- old/hcloud-cli-1.52.0/docs/reference/manual/hcloud_server-type_list.md 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/docs/reference/manual/hcloud_server-type_list.md 2025-09-25 15:00:37.000000000 +0200 @@ -8,10 +8,11 @@ Output can be controlled with the -o flag. Use -o noheader to suppress the table header. Displayed columns and their order can be set with --o columns=architecture,cores (see available columns below). +-o columns=architecture,category (see available columns below). Columns: - architecture + - category - cores - cpu_type - deprecated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/go.mod new/hcloud-cli-1.53.0/go.mod --- old/hcloud-cli-1.52.0/go.mod 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/go.mod 2025-09-25 15:00:37.000000000 +0200 @@ -12,16 +12,16 @@ github.com/fatih/structs v1.1.0 github.com/goccy/go-yaml v1.18.0 github.com/guptarohit/asciigraph v0.7.3 - github.com/hetznercloud/hcloud-go/v2 v2.22.0 + github.com/hetznercloud/hcloud-go/v2 v2.25.0 github.com/jedib0t/go-pretty/v6 v6.6.8 - github.com/spf13/cast v1.9.2 + github.com/spf13/cast v1.10.0 github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 - github.com/spf13/viper v1.20.1 + github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 github.com/swaggest/assertjson v1.9.0 go.uber.org/mock v0.6.0 - golang.org/x/crypto v0.41.0 + golang.org/x/crypto v0.42.0 golang.org/x/term v0.35.0 golang.org/x/text v0.29.0 ) @@ -33,8 +33,8 @@ github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect @@ -42,25 +42,25 @@ github.com/mattn/go-runewidth v0.0.16 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.11 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.7.0 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - golang.org/x/net v0.42.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/sys v0.36.0 // indirect - google.golang.org/protobuf v1.36.5 // 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.52.0/go.sum new/hcloud-cli-1.53.0/go.sum --- old/hcloud-cli-1.52.0/go.sum 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/go.sum 2025-09-25 15:00:37.000000000 +0200 @@ -27,18 +27,18 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +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.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/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.22.0 h1:RwcOkgB5y7kvi9Nxt40lHej8HjaS/P+9Yjfs4Glcds0= -github.com/hetznercloud/hcloud-go/v2 v2.22.0/go.mod h1:t14Logj+iLXyS03DGwEyrN+y7/C9243CJt3IArTHbyM= +github.com/hetznercloud/hcloud-go/v2 v2.25.0 h1:vW8rC+ArxSAI7YYkRWQf+7CKnYE+Z++MabzZADaPvi4= +github.com/hetznercloud/hcloud-go/v2 v2.25.0/go.mod h1:uQdAWaW3d9TimiyOjQWY8HKShs0Nd6S4wNYqo0HjvIY= 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= @@ -70,19 +70,19 @@ github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -90,25 +90,24 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= @@ -122,16 +121,18 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +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.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= @@ -140,8 +141,8 @@ golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +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= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/base/delete.go new/hcloud-cli-1.53.0/internal/cmd/base/delete.go --- old/hcloud-cli-1.52.0/internal/cmd/base/delete.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/base/delete.go 2025-09-25 15:00:37.000000000 +0200 @@ -3,6 +3,7 @@ import ( "errors" "fmt" + "log" "slices" "strings" @@ -22,25 +23,57 @@ ShortDescription string NameSuggestions func(client hcapi2.Client) func() []string AdditionalFlags func(*cobra.Command) - Fetch func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) + Fetch FetchFunc Delete func(s state.State, cmd *cobra.Command, resource interface{}) (*hcloud.Action, error) + // FetchFunc is a factory function that produces [DeleteCmd.Fetch]. Should be set in case the resource has + // more than a single identifier that is used in the positional arguments. + // See [DeleteCmd.PositionalArgumentOverride]. + FetchFunc func(s state.State, cmd *cobra.Command, args []string) (FetchFunc, error) + + // In case the resource does not have a single identifier that matches [DeleteCmd.ResourceNameSingular], this field + // can be set to define the list of positional arguments. + // For example, passing: + // []string{"a", "b", "c"} + // Would result in the usage string: + // <a> <b> <c>... + // Where c is are resources to be deleted. + PositionalArgumentOverride []string + + // Can be set if the default [DeleteCmd.NameSuggestions] is not enough. This is usually the case when + // [DeleteCmd.FetchWithArgs] and [DeleteCmd.PositionalArgumentOverride] is being used. + ValidArgsFunction func(client hcapi2.Client) []cobra.CompletionFunc + // Experimental is a function that will be used to mark the command as experimental. Experimental func(state.State, *cobra.Command) *cobra.Command } +type FetchFunc func(s state.State, cmd *cobra.Command, idOrName string) (any, *hcloud.Response, error) + // CobraCommand creates a command that can be registered with cobra. func (dc *DeleteCmd) CobraCommand(s state.State) *cobra.Command { + var suggestArgs []cobra.CompletionFunc + switch { + case dc.NameSuggestions != nil: + suggestArgs = append(suggestArgs, + cmpl.SuggestCandidatesF(dc.NameSuggestions(s.Client())), + ) + case dc.ValidArgsFunction != nil: + suggestArgs = append(suggestArgs, dc.ValidArgsFunction(s.Client())...) + default: + log.Fatalf("delete command %s is missing ValidArgsFunction or NameSuggestions", dc.ResourceNameSingular) + } + opts := "" if dc.AdditionalFlags != nil { opts = "[options] " } cmd := &cobra.Command{ - Use: fmt.Sprintf("delete %s<%s>...", opts, util.ToKebabCase(dc.ResourceNameSingular)), + Use: fmt.Sprintf("delete %s%s...", opts, positionalArguments(dc.ResourceNameSingular, dc.PositionalArgumentOverride)), Short: dc.ShortDescription, Args: util.Validate, - ValidArgsFunction: cmpl.SuggestCandidatesF(dc.NameSuggestions(s.Client())), + ValidArgsFunction: cmpl.SuggestArgs(suggestArgs...), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(s.EnsureToken), @@ -62,17 +95,32 @@ // Run executes a delete command. func (dc *DeleteCmd) Run(s state.State, cmd *cobra.Command, args []string) error { - errs := make([]error, 0, len(args)) - deleted := make([]string, 0, len(args)) + toDelete := args[max(0, len(dc.PositionalArgumentOverride)-1):] + + errs := make([]error, 0, len(toDelete)) + deleted := make([]string, 0, len(toDelete)) + + var ( + fetch FetchFunc + err error + ) + if dc.FetchFunc != nil { + fetch, err = dc.FetchFunc(s, cmd, args) + if err != nil { + return err + } + } else { + fetch = dc.Fetch + } - for batch := range slices.Chunk(args, deleteBatchSize) { + for batch := range slices.Chunk(toDelete, deleteBatchSize) { results := make([]util.ResourceState, len(batch)) actions := make([]*hcloud.Action, 0, len(batch)) for i, idOrName := range batch { results[i] = util.ResourceState{IDOrName: idOrName} - resource, _, err := dc.Fetch(s, cmd, idOrName) + resource, _, err := fetch(s, cmd, idOrName) if err != nil { results[i].Error = err continue diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/base/update.go new/hcloud-cli-1.53.0/internal/cmd/base/update.go --- old/hcloud-cli-1.52.0/internal/cmd/base/update.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/base/update.go 2025-09-25 15:00:37.000000000 +0200 @@ -2,6 +2,7 @@ import ( "fmt" + "log" "reflect" "github.com/spf13/cobra" @@ -20,8 +21,25 @@ ShortDescription string NameSuggestions func(client hcapi2.Client) func() []string DefineFlags func(*cobra.Command) - Fetch func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) - Update func(s state.State, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error + + Fetch func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) + // Can be set in case the resource has more than a single identifier that is used in the positional arguments. + // See [UpdateCmd.PositionalArgumentOverride]. + FetchWithArgs func(s state.State, cmd *cobra.Command, args []string) (any, *hcloud.Response, error) + + Update func(s state.State, cmd *cobra.Command, resource interface{}, flags map[string]pflag.Value) error + + // In case the resource does not have a single identifier that matches [UpdateCmd.ResourceNameSingular], this field + // can be set to define the list of positional arguments. + // For example, passing: + // []string{"a", "b", "c"} + // Would result in the usage string: + // <a> <b> <c> + PositionalArgumentOverride []string + + // Can be set if the default [UpdateCmd.NameSuggestions] is not enough. This is usually the case when + // [UpdateCmd.FetchWithArgs] and [UpdateCmd.PositionalArgumentOverride] is being used. + ValidArgsFunction func(client hcapi2.Client) []cobra.CompletionFunc // Experimental is a function that will be used to mark the command as experimental. Experimental func(state.State, *cobra.Command) *cobra.Command @@ -29,11 +47,23 @@ // CobraCommand creates a command that can be registered with cobra. func (uc *UpdateCmd) CobraCommand(s state.State) *cobra.Command { + var suggestArgs []cobra.CompletionFunc + switch { + case uc.NameSuggestions != nil: + suggestArgs = append(suggestArgs, + cmpl.SuggestCandidatesF(uc.NameSuggestions(s.Client())), + ) + case uc.ValidArgsFunction != nil: + suggestArgs = append(suggestArgs, uc.ValidArgsFunction(s.Client())...) + default: + log.Fatalf("update command %s is missing ValidArgsFunction or NameSuggestions", uc.ResourceNameSingular) + } + cmd := &cobra.Command{ - Use: fmt.Sprintf("update [options] <%s>", util.ToKebabCase(uc.ResourceNameSingular)), + Use: fmt.Sprintf("update [options] %s", positionalArguments(uc.ResourceNameSingular, uc.PositionalArgumentOverride)), Short: uc.ShortDescription, Args: util.Validate, - ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(uc.NameSuggestions(s.Client()))), + ValidArgsFunction: cmpl.SuggestArgs(suggestArgs...), TraverseChildren: true, DisableFlagsInUseLine: true, PreRunE: util.ChainRunE(s.EnsureToken), @@ -50,12 +80,21 @@ // Run executes a update command. func (uc *UpdateCmd) Run(s state.State, cmd *cobra.Command, args []string) error { - idOrName := args[0] - resource, _, err := uc.Fetch(s, cmd, idOrName) + var ( + resource any + err error + ) + if uc.FetchWithArgs != nil { + resource, _, err = uc.FetchWithArgs(s, cmd, args) + } else { + resource, _, err = uc.Fetch(s, cmd, args[0]) + } if err != nil { return err } + idOrName := args[len(args)-1] + // resource is an interface that always has a type, so the interface is never nil // (i.e. == nil) is always false. if reflect.ValueOf(resource).IsNil() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/change_type.go new/hcloud-cli-1.53.0/internal/cmd/server/change_type.go --- old/hcloud-cli-1.52.0/internal/cmd/server/change_type.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/change_type.go 2025-09-25 15:00:37.000000000 +0200 @@ -47,9 +47,7 @@ return fmt.Errorf("Server Type not found: %s", serverTypeIDOrName) } - if serverType.IsDeprecated() { - cmd.Print(warningDeprecatedServerType(serverType)) - } + cmd.Print(deprecatedServerTypeWarning(serverType, server.Datacenter.Location.Name)) keepDisk, _ := cmd.Flags().GetBool("keep-disk") opts := hcloud.ServerChangeTypeOpts{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/change_type_test.go new/hcloud-cli-1.53.0/internal/cmd/server/change_type_test.go --- old/hcloud-cli-1.52.0/internal/cmd/server/change_type_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/change_type_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -19,8 +19,8 @@ cmd := server.ChangeTypeCmd.CobraCommand(fx.State()) fx.ExpectEnsureToken() - srv := &hcloud.Server{ID: 123, Name: "my-server"} - st := &hcloud.ServerType{ID: 456, Name: "cax21"} + srv := &hcloud.Server{ID: 123, Name: "my-server", Datacenter: &hcloud.Datacenter{Location: &hcloud.Location{Name: "fsn1"}}} + st := &hcloud.ServerType{ID: 456, Name: "cax21", Locations: []hcloud.ServerTypeLocation{{Location: &hcloud.Location{Name: "fsn1"}}}} fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), "my-server"). @@ -53,8 +53,8 @@ cmd := server.ChangeTypeCmd.CobraCommand(fx.State()) fx.ExpectEnsureToken() - srv := &hcloud.Server{ID: 123, Name: "my-server"} - st := &hcloud.ServerType{ID: 456, Name: "cax21"} + srv := &hcloud.Server{ID: 123, Name: "my-server", Datacenter: &hcloud.Datacenter{Location: &hcloud.Location{Name: "fsn1"}}} + st := &hcloud.ServerType{ID: 456, Name: "cax21", Locations: []hcloud.ServerTypeLocation{{Location: &hcloud.Location{Name: "fsn1"}}}} fx.Client.ServerClient.EXPECT(). Get(gomock.Any(), "my-server"). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/create.go new/hcloud-cli-1.53.0/internal/cmd/server/create.go --- old/hcloud-cli-1.52.0/internal/cmd/server/create.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/create.go 2025-09-25 15:00:37.000000000 +0200 @@ -105,6 +105,16 @@ return nil, nil, err } + // Check if intended server type is deprecated in the requested location + var locName string + if createOpts.Location != nil { + locName = createOpts.Location.Name + } else if createOpts.Datacenter != nil { + locName = createOpts.Datacenter.Location.Name + } + + cmd.Print(deprecatedServerTypeWarning(createOpts.ServerType, locName)) + result, _, err := s.Client().Server().Create(s, createOpts) if err != nil { return nil, nil, err @@ -244,8 +254,8 @@ name, _ := flags.GetString("name") serverTypeName, _ := flags.GetString("type") imageIDorName, _ := flags.GetString("image") - location, _ := flags.GetString("location") - datacenter, _ := flags.GetString("datacenter") + locationIDOrName, _ := flags.GetString("location") + datacenterIDOrName, _ := flags.GetString("datacenter") userDataFiles, _ := flags.GetStringArray("user-data-from-file") startAfterCreate, _ := flags.GetBool("start-after-create") sshKeys, _ := flags.GetStringSlice("ssh-key") @@ -271,10 +281,6 @@ return } - if serverType.IsDeprecated() { - cmd.Print(warningDeprecatedServerType(serverType)) - } - // Select correct image based on Server Type architecture image, _, err := s.Client().Image().GetForArchitecture(s, imageIDorName, serverType.Architecture) if err != nil { @@ -424,12 +430,31 @@ createOpts.Firewalls = append(createOpts.Firewalls, &hcloud.ServerCreateFirewall{Firewall: *firewall}) } - if datacenter != "" { - createOpts.Datacenter = &hcloud.Datacenter{Name: datacenter} + if datacenterIDOrName != "" { + var datacenter *hcloud.Datacenter + datacenter, _, err = s.Client().Datacenter().Get(s, datacenterIDOrName) + if err != nil { + return + } + if datacenter == nil { + err = fmt.Errorf("Datacenter not found: %s", datacenterIDOrName) + return + } + createOpts.Datacenter = datacenter } - if location != "" { - createOpts.Location = &hcloud.Location{Name: location} + if locationIDOrName != "" { + var location *hcloud.Location + location, _, err = s.Client().Location().Get(s, locationIDOrName) + if err != nil { + return + } + if location == nil { + err = fmt.Errorf("Location not found: %s", locationIDOrName) + return + } + createOpts.Location = location } + if placementGroupIDorName != "" { var placementGroup *hcloud.PlacementGroup placementGroup, _, err = s.Client().PlacementGroup().Get(s, placementGroupIDorName) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/create_test.go new/hcloud-cli-1.53.0/internal/cmd/server/create_test.go --- old/hcloud-cli-1.52.0/internal/cmd/server/create_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/create_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -30,7 +30,7 @@ fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cx22"). - Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86}, nil, nil) + Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86, Locations: []hcloud.ServerTypeLocation{{Location: &hcloud.Location{Name: "fsn1"}}}}, nil, nil) fx.Client.ImageClient.EXPECT(). GetForArchitecture(gomock.Any(), "ubuntu-20.04", hcloud.ArchitectureX86). Return(&hcloud.Image{}, nil, nil) @@ -151,6 +151,20 @@ Disk: 20, StorageType: "local", Architecture: hcloud.ArchitectureX86, + Locations: []hcloud.ServerTypeLocation{ + { + Location: &hcloud.Location{ + ID: 1, + Name: "fsn1", + }, + }, + { + Location: &hcloud.Location{ + ID: 2, + Name: "nbg1", + }, + }, + }, }, Image: &hcloud.Image{ ID: 1, @@ -179,7 +193,7 @@ fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cx22"). - Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86}, nil, nil) + Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86, Locations: []hcloud.ServerTypeLocation{{Location: &hcloud.Location{Name: "fsn1"}}}}, nil, nil) fx.Client.ImageClient.EXPECT(). GetForArchitecture(gomock.Any(), "ubuntu-20.04", hcloud.ArchitectureX86). Return(&hcloud.Image{}, nil, nil) @@ -222,7 +236,7 @@ fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cx22"). - Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86}, nil, nil) + Return(&hcloud.ServerType{Architecture: hcloud.ArchitectureX86, Locations: []hcloud.ServerTypeLocation{{Location: &hcloud.Location{Name: "fsn1"}}}}, nil, nil) fx.Client.ImageClient.EXPECT(). GetForArchitecture(gomock.Any(), "ubuntu-20.04", hcloud.ArchitectureX86). Return(&hcloud.Image{}, nil, nil) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/describe.go new/hcloud-cli-1.53.0/internal/cmd/server/describe.go --- old/hcloud-cli-1.52.0/internal/cmd/server/describe.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/describe.go 2025-09-25 15:00:37.000000000 +0200 @@ -2,6 +2,7 @@ import ( "fmt" + "slices" humanize "github.com/dustin/go-humanize" "github.com/spf13/cobra" @@ -40,8 +41,15 @@ cmd.Printf(" Disk:\t\t%d GB\n", server.PrimaryDiskSize) cmd.Printf(" Storage Type:\t%s\n", server.ServerType.StorageType) - if text := util.DescribeDeprecation(server.ServerType); text != "" { - cmd.Print(util.PrefixLines(text, " ")) + // As we already know the location the server is in, we can show the deprecation info + // of that server type in that specific location. + locationInfoIndex := slices.IndexFunc(server.ServerType.Locations, func(locInfo hcloud.ServerTypeLocation) bool { + return locInfo.Location.Name == server.Datacenter.Location.Name + }) + if locationInfoIndex >= 0 { + if text := util.DescribeDeprecation(server.ServerType.Locations[locationInfoIndex]); text != "" { + cmd.Print(util.PrefixLines(text, " ")) + } } cmd.Printf("Public Net:\n") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/describe_test.go new/hcloud-cli-1.53.0/internal/cmd/server/describe_test.go --- old/hcloud-cli-1.52.0/internal/cmd/server/describe_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/describe_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -25,6 +25,11 @@ cmd := server.DescribeCmd.CobraCommand(fx.State()) fx.ExpectEnsureToken() + serverTypeDeprecation := hcloud.DeprecatableResource{Deprecation: &hcloud.DeprecationInfo{ + Announced: time.Date(2036, 1, 1, 0, 0, 0, 0, time.UTC), + UnavailableAfter: time.Date(2036, 4, 1, 0, 0, 0, 0, time.UTC), + }} + srv := &hcloud.Server{ ID: 123, Name: "test", @@ -37,6 +42,15 @@ Memory: 4.0, Disk: 40, StorageType: hcloud.StorageTypeLocal, + Locations: []hcloud.ServerTypeLocation{ + { + Location: &hcloud.Location{Name: "fsn1"}, + }, + { + Location: &hcloud.Location{Name: "hel1"}, + DeprecatableResource: serverTypeDeprecation, + }, + }, }, Image: &hcloud.Image{ ID: 123, @@ -91,6 +105,9 @@ Memory: 4 GB Disk: 0 GB Storage Type: local + Deprecation: + Announced: %s (%s) + Unavailable After: %s (%s) Public Net: IPv4: No Primary IPv4 @@ -142,7 +159,10 @@ No Placement Group set `, util.Datetime(srv.Created), humanize.Time(srv.Created), - util.Datetime(srv.Image.Created), humanize.Time(srv.Image.Created)) + util.Datetime(serverTypeDeprecation.DeprecationAnnounced()), humanize.Time(serverTypeDeprecation.DeprecationAnnounced()), + util.Datetime(serverTypeDeprecation.UnavailableAfter()), humanize.Time(serverTypeDeprecation.UnavailableAfter()), + util.Datetime(srv.Image.Created), humanize.Time(srv.Image.Created), + ) require.NoError(t, err) assert.Empty(t, errOut) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/testdata/create_response.json new/hcloud-cli-1.53.0/internal/cmd/server/testdata/create_response.json --- old/hcloud-cli-1.52.0/internal/cmd/server/testdata/create_response.json 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/testdata/create_response.json 2025-09-25 15:00:37.000000000 +0200 @@ -87,6 +87,7 @@ "rescue_enabled": true, "server_type": { "architecture": "x86", + "category": "", "cores": 1, "cpu_type": "shared", "deprecated": false, @@ -98,7 +99,11 @@ "memory": 2, "name": "cx22", "prices": null, - "storage_type": "local" + "storage_type": "local", + "locations": [ + { "id": 1, "name": "fsn1", "deprecation": null }, + { "id": 2, "name": "nbg1", "deprecation": null } + ] }, "status": "running", "volumes": null diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/server/texts.go new/hcloud-cli-1.53.0/internal/cmd/server/texts.go --- old/hcloud-cli-1.52.0/internal/cmd/server/texts.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/server/texts.go 2025-09-25 15:00:37.000000000 +0200 @@ -2,19 +2,21 @@ import ( "fmt" - "time" "github.com/hetznercloud/hcloud-go/v2/hcloud" + "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/deprecationutil" ) -func warningDeprecatedServerType(serverType *hcloud.ServerType) string { - if !serverType.IsDeprecated() { - return "" - } +const ChangeDeprecatedServerTypeMessage = (`Existing servers of that plan will ` + + `continue to work as before and no action is required on your part. ` + + `It is possible to migrate this Server to another Server Type by using ` + + `the "hcloud server change-type" command.`) - if time.Now().After(serverType.UnavailableAfter()) { - return fmt.Sprintf("Attention: The Server Type %q is deprecated and can no longer be ordered. Existing servers of that plan will continue to work as before and no action is required on your part. It is possible to migrate this Server to another Server Type by using the \"hcloud server change-type\" command.\n\n", serverType.Name) +func deprecatedServerTypeWarning(serverType *hcloud.ServerType, locationName string) string { + warnText, _ := deprecationutil.ServerTypeWarning(serverType, locationName) + if warnText == "" { + return "" } - return fmt.Sprintf("Attention: The Server Type %q is deprecated and will no longer be available for order as of %s. Existing servers of that plan will continue to work as before and no action is required on your part. It is possible to migrate this Server to another Server Type by using the \"hcloud server change-type\" command.\n\n", serverType.Name, serverType.UnavailableAfter().Format(time.DateOnly)) + return fmt.Sprintf("Attention: %s %s\n\n", warnText, ChangeDeprecatedServerTypeMessage) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/servertype/describe.go new/hcloud-cli-1.53.0/internal/cmd/servertype/describe.go --- old/hcloud-cli-1.52.0/internal/cmd/servertype/describe.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/servertype/describe.go 2025-09-25 15:00:37.000000000 +0200 @@ -26,29 +26,35 @@ cmd.Printf("ID:\t\t\t%d\n", serverType.ID) cmd.Printf("Name:\t\t\t%s\n", serverType.Name) cmd.Printf("Description:\t\t%s\n", serverType.Description) + cmd.Printf("Category:\t\t%s\n", serverType.Category) cmd.Printf("Cores:\t\t\t%d\n", serverType.Cores) cmd.Printf("CPU Type:\t\t%s\n", serverType.CPUType) cmd.Printf("Architecture:\t\t%s\n", serverType.Architecture) cmd.Printf("Memory:\t\t\t%.1f GB\n", serverType.Memory) cmd.Printf("Disk:\t\t\t%d GB\n", serverType.Disk) cmd.Printf("Storage Type:\t\t%s\n", serverType.StorageType) - cmd.Print(util.DescribeDeprecation(serverType)) pricings, err := fullPricingInfo(s, serverType) if err != nil { cmd.PrintErrf("failed to get prices for Server Type: %v", err) } - if pricings != nil { - cmd.Printf("Pricings per Location:\n") - for _, price := range pricings { - cmd.Printf(" - Location:\t\t%s\n", price.Location.Name) - cmd.Printf(" Hourly:\t\t%s\n", util.GrossPrice(price.Hourly)) - cmd.Printf(" Monthly:\t\t%s\n", util.GrossPrice(price.Monthly)) - cmd.Printf(" Included Traffic:\t%s\n", humanize.IBytes(price.IncludedTraffic)) - cmd.Printf(" Additional Traffic:\t%s per TB\n", util.GrossPrice(price.PerTBTraffic)) - cmd.Printf("\n") + locations := joinLocationInfo(serverType, pricings) + cmd.Printf("Locations:\n") + for _, info := range locations { + + cmd.Printf(" - Location:\t\t%s\n", info.Location.Name) + + if deprecationText := util.DescribeDeprecation(info); deprecationText != "" { + cmd.Print(util.PrefixLines(deprecationText, " ")) } + + cmd.Printf(" Pricing:\n") + cmd.Printf(" Hourly:\t\t%s\n", util.GrossPrice(info.Pricing.Hourly)) + cmd.Printf(" Monthly:\t\t%s\n", util.GrossPrice(info.Pricing.Monthly)) + cmd.Printf(" Included Traffic:\t%s\n", humanize.IBytes(info.Pricing.IncludedTraffic)) + cmd.Printf(" Additional Traffic:\t%s per TB\n", util.GrossPrice(info.Pricing.PerTBTraffic)) + cmd.Printf("\n") } return nil @@ -69,3 +75,29 @@ return nil, nil } + +type locationInfo struct { + Location *hcloud.Location + hcloud.DeprecatableResource + Pricing hcloud.ServerTypeLocationPricing +} + +func joinLocationInfo(serverType *hcloud.ServerType, pricings []hcloud.ServerTypeLocationPricing) []locationInfo { + locations := make([]locationInfo, 0, len(serverType.Locations)) + + for _, location := range serverType.Locations { + info := locationInfo{Location: location.Location, DeprecatableResource: location.DeprecatableResource} + + for _, pricing := range pricings { + // Pricing endpoint only sets the location name + if pricing.Location.Name == info.Location.Name { + info.Pricing = pricing + break + } + } + + locations = append(locations, info) + } + + return locations +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/servertype/describe_test.go new/hcloud-cli-1.53.0/internal/cmd/servertype/describe_test.go --- old/hcloud-cli-1.52.0/internal/cmd/servertype/describe_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/servertype/describe_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -1,13 +1,17 @@ package servertype_test import ( + "fmt" "testing" + "time" + "github.com/dustin/go-humanize" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/hetznercloud/cli/internal/cmd/servertype" + "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/testutil" "github.com/hetznercloud/hcloud-go/v2/hcloud" ) @@ -19,17 +23,29 @@ cmd := servertype.DescribeCmd.CobraCommand(fx.State()) fx.ExpectEnsureToken() + deprecation := hcloud.DeprecatableResource{Deprecation: &hcloud.DeprecationInfo{ + Announced: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC), + UnavailableAfter: time.Date(2025, 4, 1, 0, 0, 0, 0, time.UTC), + }} + fx.Client.ServerTypeClient.EXPECT(). Get(gomock.Any(), "cax11"). Return(&hcloud.ServerType{ ID: 45, Name: "cax11", Description: "CAX11", + Category: "Shared vCPU", Cores: 2, CPUType: hcloud.CPUTypeShared, Memory: 4.0, Disk: 40, StorageType: hcloud.StorageTypeLocal, + Locations: []hcloud.ServerTypeLocation{ + { + Location: &hcloud.Location{Name: "fsn1"}, + DeprecatableResource: deprecation, + }, + }, }, nil, nil) fx.Client.PricingClient.EXPECT(). @@ -41,7 +57,7 @@ ServerType: &hcloud.ServerType{ID: 1}, Pricings: []hcloud.ServerTypeLocationPricing{{ Location: &hcloud.Location{ - Name: "Nuremberg", + Name: "nbg1", }, Hourly: hcloud.Price{ Gross: "4.0000", @@ -62,7 +78,7 @@ ServerType: &hcloud.ServerType{ID: 45}, Pricings: []hcloud.ServerTypeLocationPricing{{ Location: &hcloud.Location{ - Name: "Falkenstein", + Name: "fsn1", }, Hourly: hcloud.Price{ Gross: "1.0000", @@ -84,23 +100,30 @@ out, errOut, err := fx.Run(cmd, []string{"cax11"}) - expOut := `ID: 45 + expOut := fmt.Sprintf(`ID: 45 Name: cax11 Description: CAX11 +Category: Shared vCPU Cores: 2 CPU Type: shared Architecture: Memory: 4.0 GB Disk: 40 GB Storage Type: local -Pricings per Location: - - Location: Falkenstein - Hourly: € 1.0000 - Monthly: € 2.0000 - Included Traffic: 639 KiB - Additional Traffic: € 3.0000 per TB - -` +Locations: + - Location: fsn1 + Deprecation: + Announced: %s (%s) + Unavailable After: %s (%s) + Pricing: + Hourly: € 1.0000 + Monthly: € 2.0000 + Included Traffic: 639 KiB + Additional Traffic: € 3.0000 per TB + +`, + util.Datetime(deprecation.DeprecationAnnounced()), humanize.Time(deprecation.DeprecationAnnounced()), + util.Datetime(deprecation.UnavailableAfter()), humanize.Time(deprecation.UnavailableAfter())) require.NoError(t, err) assert.Empty(t, errOut) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/servertype/list.go new/hcloud-cli-1.53.0/internal/cmd/servertype/list.go --- old/hcloud-cli-1.52.0/internal/cmd/servertype/list.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/servertype/list.go 2025-09-25 15:00:37.000000000 +0200 @@ -2,12 +2,13 @@ import ( "fmt" + "strings" + "time" "github.com/spf13/pflag" "github.com/hetznercloud/cli/internal/cmd/base" "github.com/hetznercloud/cli/internal/cmd/output" - "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/hcloud-go/v2/hcloud" @@ -47,10 +48,21 @@ }). AddFieldFn("deprecated", func(obj interface{}) string { serverType := obj.(*hcloud.ServerType) - if !serverType.IsDeprecated() { - return "-" + + deprecatedInfos := make([]string, 0, len(serverType.Locations)) + for _, loc := range serverType.Locations { + if loc.IsDeprecated() { + deprecatedInfos = append( + deprecatedInfos, + fmt.Sprintf("%s=%s", loc.Location.Name, loc.UnavailableAfter().Local().Format(time.DateOnly)), + ) + } + } + + if len(deprecatedInfos) > 0 { + return strings.Join(deprecatedInfos, ",") } - return util.Datetime(serverType.UnavailableAfter()) + return "-" }) }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/cmd/servertype/list_test.go new/hcloud-cli-1.53.0/internal/cmd/servertype/list_test.go --- old/hcloud-cli-1.52.0/internal/cmd/servertype/list_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/cmd/servertype/list_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -75,10 +75,20 @@ { ID: 123, Name: "deprecated", - DeprecatableResource: hcloud.DeprecatableResource{ - Deprecation: &hcloud.DeprecationInfo{ - Announced: time.Date(2036, 8, 20, 12, 0, 0, 0, time.UTC), - UnavailableAfter: time.Date(2037, 8, 20, 12, 0, 0, 0, time.UTC), + Locations: []hcloud.ServerTypeLocation{ + { + Location: &hcloud.Location{Name: "fsn1"}, + DeprecatableResource: hcloud.DeprecatableResource{Deprecation: &hcloud.DeprecationInfo{ + Announced: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC), + UnavailableAfter: time.Date(2025, 4, 1, 0, 0, 0, 0, time.UTC), + }}, + }, + { + Location: &hcloud.Location{Name: "nbg1"}, + DeprecatableResource: hcloud.DeprecatableResource{Deprecation: &hcloud.DeprecationInfo{ + Announced: time.Date(2025, 2, 1, 0, 0, 0, 0, time.UTC), + UnavailableAfter: time.Date(2025, 5, 1, 0, 0, 0, 0, time.UTC), + }}, }, }, }, @@ -90,9 +100,9 @@ out, errOut, err := fx.Run(cmd, []string{"-o=columns=id,name,deprecated"}) - expOut := `ID NAME DEPRECATED -123 deprecated Thu Aug 20 12:00:00 UTC 2037 -124 current - + expOut := `ID NAME DEPRECATED +123 deprecated fsn1=2025-04-01,nbg1=2025-05-01 +124 current - ` require.NoError(t, err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-cli-1.52.0/internal/version/version.go new/hcloud-cli-1.53.0/internal/version/version.go --- old/hcloud-cli-1.52.0/internal/version/version.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/internal/version/version.go 2025-09-25 15:00:37.000000000 +0200 @@ -2,7 +2,7 @@ var ( // version is a semver version (https://semver.org). - version = "1.52.0" // x-releaser-pleaser-version + version = "1.53.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.52.0/test/e2e/firewall_test.go new/hcloud-cli-1.53.0/test/e2e/firewall_test.go --- old/hcloud-cli-1.52.0/test/e2e/firewall_test.go 2025-09-08 11:46:53.000000000 +0200 +++ new/hcloud-cli-1.53.0/test/e2e/firewall_test.go 2025-09-25 15:00:37.000000000 +0200 @@ -181,6 +181,12 @@ Lit(" Source IPs:").Newline(). Whitespace().Lit("0.0.0.0/0").Newline(). Whitespace().Lit("::/0").Newline(). + Lit(" - Direction:").Whitespace().Lit("in").Newline(). + Lit(" Description:").Whitespace().Lit("Some random description").Newline(). + Lit(" Protocol:").Whitespace().Lit("tcp").Newline(). + Lit(" Port:").Whitespace().Lit("9100").Newline(). + Lit(" Source IPs:").Newline(). + Whitespace().Lit("10.0.0.0/24").Newline(). Lit(" - Direction:").Whitespace().Lit("out").Newline(). Lit(" Protocol:").Whitespace().Lit("tcp").Newline(). Lit(" Port:").Whitespace().Lit("80").Newline(). @@ -188,12 +194,6 @@ Whitespace().Lit("28.239.13.1/32").Newline(). Whitespace().Lit("28.239.14.0/24").Newline(). Whitespace().Lit("ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128").Newline(). - Lit(" - Direction:").Whitespace().Lit("in").Newline(). - Lit(" Description:").Whitespace().Lit("Some random description").Newline(). - Lit(" Protocol:").Whitespace().Lit("tcp").Newline(). - Lit(" Port:").Whitespace().Lit("9100").Newline(). - Lit(" Source IPs:").Newline(). - Whitespace().Lit("10.0.0.0/24").Newline(). Lit(" - Direction:").Whitespace().Lit("out").Newline(). Lit(" Protocol:").Whitespace().Lit("icmp").Newline(). Lit(" Destination IPs:").Newline(). ++++++ hcloud-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.r3Dub9/_old 2025-09-26 22:26:17.478485097 +0200 +++ /var/tmp/diff_new_pack.r3Dub9/_new 2025-09-26 22:26:17.482485265 +0200 @@ -1,5 +1,5 @@ name: hcloud-cli -version: 1.52.0 -mtime: 1757324813 -commit: 6dec460911978e46fdf9127e3c6b411c722efe89 +version: 1.53.0 +mtime: 1758805237 +commit: 29f8f3b2f5f60c9b16b44abb980467a043d5891e ++++++ vendor.tar.gz ++++++ ++++ 38115 lines of diff (skipped)
