├── .gitlab └── CODEOWNERS ├── codecov.yml ├── .github ├── CODEOWNERS └── workflows │ ├── releaser-pleaser.yml │ ├── build.yml │ └── links.yml ├── internal ├── cmd │ ├── zone │ │ ├── zone_test.go │ │ ├── rrset │ │ │ └── rrset_test.go │ │ ├── testdata │ │ │ ├── example.zone │ │ │ ├── primary_nameservers.json │ │ │ └── create_response.json │ │ ├── delete.go │ │ └── change_ttl_test.go │ ├── certificate │ │ ├── testdata │ │ │ ├── key.pem │ │ │ ├── cert.pem │ │ │ ├── uploaded_create_response.json │ │ │ └── managed_create_response.json │ │ ├── certificate.go │ │ ├── delete.go │ │ ├── update_test.go │ │ └── update.go │ ├── util │ │ ├── resource.go │ │ ├── byte_units.go │ │ ├── deprecation.go │ │ └── idna.go │ ├── storagebox │ │ ├── storage_box_test.go │ │ ├── snapshot │ │ │ ├── snapshot_test.go │ │ │ ├── testdata │ │ │ │ └── create_response.json │ │ │ ├── snapshot.go │ │ │ └── cmpl.go │ │ ├── subaccount │ │ │ ├── subaccount_test.go │ │ │ ├── testdata │ │ │ │ └── create_response.json │ │ │ ├── cmpl.go │ │ │ └── subaccount.go │ │ ├── delete.go │ │ ├── update_test.go │ │ └── texts.go │ ├── storageboxtype │ │ ├── storage_box_type_test.go │ │ └── storage_box_type.go │ ├── experimental │ │ └── markers.go │ ├── sshkey │ │ ├── testdata │ │ │ └── create_response.json │ │ ├── sshkey.go │ │ ├── delete.go │ │ ├── update_test.go │ │ ├── update.go │ │ └── list_test.go │ ├── placementgroup │ │ ├── testdata │ │ │ └── create_response.json │ │ ├── placementgroup.go │ │ ├── delete.go │ │ └── update_test.go │ ├── firewall │ │ ├── validation.go │ │ ├── testdata │ │ │ ├── create_response.json │ │ │ └── rules.json │ │ ├── delete.go │ │ ├── update_test.go │ │ ├── firewall.go │ │ └── update.go │ ├── network │ │ ├── testdata │ │ │ └── create_response.json │ │ ├── delete.go │ │ └── update_test.go │ ├── all │ │ └── all.go │ ├── volume │ │ ├── testdata │ │ │ └── create_response.json │ │ ├── delete.go │ │ ├── update_test.go │ │ ├── detach_test.go │ │ ├── update.go │ │ ├── volume.go │ │ └── resize_test.go │ ├── servertype │ │ └── server_type.go │ ├── iso │ │ ├── iso.go │ │ └── describe_test.go │ ├── floatingip │ │ ├── testdata │ │ │ └── create_response.json │ │ ├── set_rdns.go │ │ ├── delete.go │ │ ├── unassign_test.go │ │ └── floatingip.go │ ├── loadbalancertype │ │ └── load_balancer_type.go │ ├── location │ │ └── location.go │ ├── datacenter │ │ └── datacenter.go │ ├── version │ │ └── version.go │ ├── context │ │ ├── context.go │ │ ├── unset.go │ │ └── active.go │ ├── server │ │ ├── texts.go │ │ ├── set_rdns.go │ │ ├── delete.go │ │ ├── update_test.go │ │ ├── reset_test.go │ │ ├── reboot_test.go │ │ ├── poweron_test.go │ │ ├── update.go │ │ ├── poweroff_test.go │ │ ├── detach_iso_test.go │ │ ├── remove_from_placement_group_test.go │ │ ├── ssh_test.go │ │ ├── disable_backup_test.go │ │ ├── disable_rescue_test.go │ │ └── enable_backup_test.go │ ├── primaryip │ │ ├── set_rdns.go │ │ ├── delete.go │ │ ├── testdata │ │ │ └── create_response.json │ │ └── primaryip.go │ ├── loadbalancer │ │ ├── set_rdns.go │ │ ├── delete.go │ │ ├── update_test.go │ │ └── delete_service_test.go │ └── image │ │ ├── image.go │ │ └── delete.go ├── hcapi2 │ ├── labels.go │ ├── rdns.go │ ├── action.go │ ├── pricing.go │ ├── iso.go │ └── datacenter.go ├── state │ ├── config │ │ ├── config_windows.go │ │ ├── config_unix.go │ │ └── config_mock.go │ ├── helpers.go │ └── command_helpers.go ├── ui │ ├── helpers.go │ ├── progress.go │ ├── actions.go │ └── progress_test.go ├── version │ └── version.go └── testutil │ └── terminal │ └── terminal.go ├── test └── e2e │ ├── config.toml │ ├── rules_file.json │ └── server_test.go ├── .gitattributes ├── .gitignore ├── .gitlab-ci.yml ├── scripts └── check-release-error.sh ├── docs ├── guides │ └── README.md ├── tutorials │ └── README.md ├── reference │ ├── README.md │ └── manual │ │ ├── hcloud_version.md │ │ ├── hcloud_context_unset.md │ │ ├── hcloud_context_use.md │ │ ├── hcloud_image_delete.md │ │ ├── hcloud_context_active.md │ │ ├── hcloud_server_reboot.md │ │ ├── hcloud_volume_detach.md │ │ ├── hcloud_server_delete.md │ │ ├── hcloud_server_poweron.md │ │ ├── hcloud_server_reset.md │ │ ├── hcloud_volume_delete.md │ │ ├── hcloud_all.md │ │ ├── hcloud_context_delete.md │ │ ├── hcloud_network_delete.md │ │ ├── hcloud_server_poweroff.md │ │ ├── hcloud_context_rename.md │ │ ├── hcloud_ssh-key_delete.md │ │ ├── hcloud_firewall_delete.md │ │ ├── hcloud_zone_delete.md │ │ ├── hcloud_iso.md │ │ ├── hcloud_server_detach-iso.md │ │ ├── hcloud_primary-ip_delete.md │ │ ├── hcloud_server_attach-iso.md │ │ ├── hcloud_certificate_delete.md │ │ ├── hcloud_floating-ip_delete.md │ │ ├── hcloud_server_disable-backup.md │ │ ├── hcloud_server_disable-rescue.md │ │ ├── hcloud_floating-ip_unassign.md │ │ ├── hcloud_zone_rrset_delete.md │ │ ├── hcloud_certificate_retry.md │ │ ├── hcloud_server_update.md │ │ ├── hcloud_volume_update.md │ │ ├── hcloud_floating-ip_assign.md │ │ ├── hcloud_load-balancer_delete.md │ │ ├── hcloud_ssh-key_update.md │ │ ├── hcloud_image_enable-protection.md │ │ ├── hcloud_firewall_update.md │ │ ├── hcloud_image_disable-protection.md │ │ ├── hcloud_iso_describe.md │ │ ├── hcloud_placement-group_delete.md │ │ ├── hcloud_volume_enable-protection.md │ │ ├── hcloud_location.md │ │ ├── hcloud_primary-ip_unassign.md │ │ ├── hcloud_volume_disable-protection.md │ │ ├── hcloud_volume_resize.md │ │ ├── hcloud_network_enable-protection.md │ │ ├── hcloud_server_ip.md │ │ ├── hcloud_image_remove-label.md │ │ ├── hcloud_network_disable-protection.md │ │ ├── hcloud_server_enable-protection.md │ │ ├── hcloud_zone_enable-protection.md │ │ ├── hcloud_server_disable-protection.md │ │ ├── hcloud_server_remove-label.md │ │ ├── hcloud_volume_remove-label.md │ │ ├── hcloud_zone_disable-protection.md │ │ ├── hcloud_certificate_update.md │ │ ├── hcloud_datacenter.md │ │ ├── hcloud_server_describe.md │ │ ├── hcloud_volume_describe.md │ │ ├── hcloud_load-balancer_change-type.md │ │ ├── hcloud_network_remove-label.md │ │ ├── hcloud_ssh-key_remove-label.md │ │ ├── hcloud_network_describe.md │ │ ├── hcloud_primary-ip_enable-protection.md │ │ ├── hcloud_server-type.md │ │ ├── hcloud_server_remove-from-placement-group.md │ │ ├── hcloud_ssh-key_describe.md │ │ ├── hcloud_zone_remove-label.md │ │ ├── hcloud_firewall_remove-label.md │ │ ├── hcloud_floating-ip_enable-protection.md │ │ ├── hcloud_image_update.md │ │ ├── hcloud_location_describe.md │ │ ├── hcloud_primary-ip_disable-protection.md │ │ ├── hcloud_zone_describe.md │ │ ├── hcloud_firewall_describe.md │ │ ├── hcloud_floating-ip_disable-protection.md │ │ ├── hcloud_image_add-label.md │ │ └── hcloud_load-balancer_update.md └── README.md ├── mise.toml ├── renovate.json ├── examples └── firewall_rules.json ├── cmd └── hcloud │ └── main.go └── LICENSE /.gitlab/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @cloud/integrations 2 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "**/zz_*.go" 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @hetznercloud/integrations 2 | -------------------------------------------------------------------------------- /internal/cmd/zone/zone_test.go: -------------------------------------------------------------------------------- 1 | package zone_test 2 | -------------------------------------------------------------------------------- /test/e2e/config.toml: -------------------------------------------------------------------------------- 1 | # config for tests goes here 2 | -------------------------------------------------------------------------------- /internal/cmd/certificate/testdata/key.pem: -------------------------------------------------------------------------------- 1 | key file content -------------------------------------------------------------------------------- /internal/cmd/zone/rrset/rrset_test.go: -------------------------------------------------------------------------------- 1 | package rrset_test 2 | -------------------------------------------------------------------------------- /internal/cmd/certificate/testdata/cert.pem: -------------------------------------------------------------------------------- 1 | certificate file content -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docs/reference/manual/*.md linguist-generated=true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /hcloud 2 | /dist 3 | /bats 4 | /cmd/hcloud/hcloud 5 | hcloud_cli.p12 6 | coverage.txt 7 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - project: cloud/integrations/ci 3 | file: 4 | - cli/.gitlab-ci.yml 5 | -------------------------------------------------------------------------------- /internal/cmd/util/resource.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type ResourceState struct { 4 | IDOrName string 5 | Error error 6 | } 7 | -------------------------------------------------------------------------------- /scripts/check-release-error.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ls -1 ./*.error || true 4 | 5 | if [[ -f sign-and-notarize.error ]]; then exit 1; fi 6 | -------------------------------------------------------------------------------- /docs/guides/README.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | This folder contains guides on how to accomplish specific tasks with the Hetzner Cloud CLI. 4 | 5 | - [Using output options](using-output-options.md) 6 | -------------------------------------------------------------------------------- /docs/tutorials/README.md: -------------------------------------------------------------------------------- 1 | # Tutorials 2 | 3 | This folder contains tutorials for the Hetzner Cloud CLI. 4 | 5 | - [Setup the hcloud CLI](setup-hcloud-cli.md) 6 | - [Creating a server](create-a-server.md) 7 | -------------------------------------------------------------------------------- /docs/reference/README.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | In this directory you will find the reference documentation for the hcloud CLI. 4 | 5 | - [Command manual](manual/hcloud.md) 6 | - [Configuration](configuration.md) 7 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/storage_box_test.go: -------------------------------------------------------------------------------- 1 | package storagebox_test 2 | 3 | const ExperimentalWarning = "Warning: Storage Box support is experimental. Use --no-experimental-warnings to suppress this warning.\n" 4 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/snapshot/snapshot_test.go: -------------------------------------------------------------------------------- 1 | package snapshot_test 2 | 3 | const ExperimentalWarning = "Warning: Storage Box support is experimental. Use --no-experimental-warnings to suppress this warning.\n" 4 | -------------------------------------------------------------------------------- /internal/cmd/util/byte_units.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | Byte = 1 5 | Kibibyte = Byte * 1024 6 | Mebibyte = Kibibyte * 1024 7 | Gibibyte = Mebibyte * 1024 8 | Tebibyte = Gibibyte * 1024 9 | ) 10 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/subaccount/subaccount_test.go: -------------------------------------------------------------------------------- 1 | package subaccount_test 2 | 3 | const ExperimentalWarning = "Warning: Storage Box support is experimental. Use --no-experimental-warnings to suppress this warning.\n" 4 | -------------------------------------------------------------------------------- /internal/cmd/storageboxtype/storage_box_type_test.go: -------------------------------------------------------------------------------- 1 | package storageboxtype_test 2 | 3 | const ExperimentalWarning = "Warning: Storage Box support is experimental. Use --no-experimental-warnings to suppress this warning.\n" 4 | -------------------------------------------------------------------------------- /internal/hcapi2/labels.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | func labelKeys(m map[string]string) []string { 4 | ks := make([]string, len(m)) 5 | i := 0 6 | for k := range m { 7 | ks[i] = k 8 | i++ 9 | } 10 | return ks 11 | } 12 | -------------------------------------------------------------------------------- /internal/cmd/experimental/markers.go: -------------------------------------------------------------------------------- 1 | package experimental 2 | 3 | import "github.com/hetznercloud/cli/internal/cmd/base" 4 | 5 | var StorageBoxes = base.ExperimentalWrapper("Storage Box support", "experimental", "https://github.com/hetznercloud/cli/issues/1202") 6 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | go = "1.25.5" 3 | "go:go.uber.org/mock/mockgen" = "v0.6.0" 4 | "github:golangci/golangci-lint" = "2.7.2" 5 | "github:goreleaser/goreleaser" = "v2.13.1" 6 | "github:anchore/quill" = "v0.5.1" 7 | "github:jstemmer/go-junit-report" = "v2.1.0" 8 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>hetznercloud/.github//renovate/default", 5 | "github>hetznercloud/.github//renovate/golang" 6 | ], 7 | "postUpdateOptions": ["gomodTidy"] 8 | } 9 | -------------------------------------------------------------------------------- /internal/cmd/sshkey/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "ssh_key": { 3 | "created": "2016-01-30T23:50:00Z", 4 | "fingerprint": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00", 5 | "id": 123, 6 | "labels": {}, 7 | "name": "test", 8 | "public_key": "test" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /internal/cmd/zone/testdata/example.zone: -------------------------------------------------------------------------------- 1 | $ORIGIN example.com. 2 | $TTL 3600 3 | 4 | @ IN SOA hydrogen.ns.hetzner.com. dns.hetzner.com. 2024010100 86400 10800 3600000 3600 5 | 6 | @ IN 10800 NS hydrogen.ns.hetzner.com. ; Some comment. 7 | @ IN 10800 NS oxygen.ns.hetzner.com. 8 | @ IN 10800 NS helium.ns.hetzner.de. 9 | -------------------------------------------------------------------------------- /internal/cmd/placementgroup/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "placement_group": { 3 | "created": "2016-01-30T23:50:00Z", 4 | "id": 897, 5 | "labels": {}, 6 | "name": "myPlacementGroup", 7 | "servers": [ 8 | 1, 9 | 2, 10 | 3 11 | ], 12 | "type": "spread" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /internal/state/config/config_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package config 4 | 5 | import ( 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | func DefaultConfigPath() string { 11 | dir := os.Getenv("APPDATA") 12 | if dir != "" { 13 | return filepath.Join(dir, "hcloud", "cli.toml") 14 | } 15 | return "" 16 | } 17 | -------------------------------------------------------------------------------- /internal/cmd/zone/testdata/primary_nameservers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "address": "198.51.100.1", 4 | "port": 53 5 | }, 6 | { 7 | "address": "203.0.113.1" 8 | }, 9 | { 10 | "address": "203.0.113.1", 11 | "port": 53, 12 | "tsig_algorithm": "hmac-sha256", 13 | "tsig_key": "example-key" 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /internal/state/config/config_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package config 4 | 5 | import ( 6 | "os/user" 7 | "path/filepath" 8 | ) 9 | 10 | func DefaultConfigPath() string { 11 | usr, err := user.Current() 12 | if err != nil { 13 | return "" 14 | } 15 | if usr.HomeDir != "" { 16 | return filepath.Join(usr.HomeDir, ".config", "hcloud", "cli.toml") 17 | } 18 | return "" 19 | } 20 | -------------------------------------------------------------------------------- /internal/cmd/firewall/validation.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func ValidateFirewallIP(ip string) (*net.IPNet, error) { 9 | i, n, err := net.ParseCIDR(ip) 10 | if err != nil { 11 | return nil, err 12 | } 13 | if i.String() != n.IP.String() { 14 | return nil, fmt.Errorf("%s is not the start of the cidr block %s", ip, n) 15 | } 16 | 17 | return n, nil 18 | } 19 | -------------------------------------------------------------------------------- /internal/hcapi2/rdns.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | import "github.com/hetznercloud/hcloud-go/v2/hcloud" 4 | 5 | // NewRDNSClient embeds the Hetzner Cloud rdns client. 6 | type RDNSClient interface { 7 | hcloud.IRDNSClient 8 | } 9 | 10 | func NewRDNSClient(client hcloud.IRDNSClient) RDNSClient { 11 | return &rdnsClient{ 12 | IRDNSClient: client, 13 | } 14 | } 15 | 16 | type rdnsClient struct { 17 | hcloud.IRDNSClient 18 | } 19 | -------------------------------------------------------------------------------- /internal/hcapi2/action.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | import ( 4 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 5 | ) 6 | 7 | // ActionClient embeds the Hetzner Cloud Action client 8 | type ActionClient interface { 9 | hcloud.IActionClient 10 | } 11 | 12 | func NewActionClient(client hcloud.IActionClient) ActionClient { 13 | return &actionClient{ 14 | IActionClient: client, 15 | } 16 | } 17 | 18 | type actionClient struct { 19 | hcloud.IActionClient 20 | } 21 | -------------------------------------------------------------------------------- /internal/state/config/config_mock.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | // We do not need to generate a gomock for the Config, since you can set config 9 | // values during tests with viper.Set() 10 | 11 | type MockConfig struct { 12 | Config 13 | } 14 | 15 | func (c *MockConfig) Write(_ io.Writer) error { 16 | // MockConfig always writes to stdout for testing purposes 17 | return c.Config.Write(os.Stdout) 18 | } 19 | 20 | var _ Config = (*MockConfig)(nil) 21 | -------------------------------------------------------------------------------- /internal/ui/helpers.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "os" 5 | 6 | "golang.org/x/term" 7 | ) 8 | 9 | // StdoutIsTerminal returns whether the CLI is run in a terminal. 10 | func StdoutIsTerminal() bool { 11 | return term.IsTerminal(int(os.Stdout.Fd())) 12 | } 13 | 14 | // TerminalWidth returns the width of the terminal. 15 | func TerminalWidth() int { 16 | width, _, err := term.GetSize(int(os.Stdout.Fd())) 17 | if err != nil { 18 | return 0 19 | } 20 | 21 | return width 22 | } 23 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/snapshot/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "snapshot": { 3 | "id": 456, 4 | "name": "snapshot-1", 5 | "description": "some-description", 6 | "stats": { 7 | "size": 53687091200, 8 | "size_filesystem": 42949672960 9 | }, 10 | "is_automatic": false, 11 | "labels": { 12 | "environment": "prod", 13 | "example.com/my": "label", 14 | "just-a-key": "" 15 | }, 16 | "created": "2024-01-02T15:04:05Z", 17 | "storage_box": 1337 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /internal/hcapi2/pricing.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | import ( 4 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 5 | ) 6 | 7 | // PricingClient embeds the Hetzner Cloud Pricing client and provides some 8 | // additional helper functions. 9 | type PricingClient interface { 10 | hcloud.IPricingClient 11 | } 12 | 13 | func NewPricingClient(client hcloud.IPricingClient) PricingClient { 14 | return &pricingClient{ 15 | IPricingClient: client, 16 | } 17 | } 18 | 19 | type pricingClient struct { 20 | hcloud.IPricingClient 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/network/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "created": "2016-01-30T23:50:00Z", 4 | "expose_routes_to_vswitch": false, 5 | "id": 123, 6 | "ip_range": "10.0.0.0/24", 7 | "labels": {}, 8 | "load_balancers": [ 9 | 4, 10 | 5, 11 | 6 12 | ], 13 | "name": "myNetwork", 14 | "protection": { 15 | "delete": false 16 | }, 17 | "routes": [], 18 | "servers": [ 19 | 1, 20 | 2, 21 | 3 22 | ], 23 | "subnets": [] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /internal/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | var ( 4 | // version is a semver version (https://semver.org). 5 | version = "1.58.0" // x-releaser-pleaser-version 6 | 7 | // versionPrerelease is a semver version pre-release identifier (https://semver.org). 8 | // 9 | // For final releases, we set this to an empty string. 10 | versionPrerelease = "dev" 11 | 12 | // Version of the hcloud CLI. 13 | Version = func() string { 14 | if versionPrerelease != "" { 15 | return version + "-" + versionPrerelease 16 | } 17 | return version 18 | }() 19 | ) 20 | -------------------------------------------------------------------------------- /examples/firewall_rules.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "direction": "in", 4 | "source_ips": [ 5 | "28.239.13.1/32", 6 | "28.239.14.0/24", 7 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 8 | ], 9 | "destination_ips": [], 10 | "protocol": "tcp", 11 | "port": "80" 12 | }, 13 | { 14 | "direction": "out", 15 | "source_ips": [], 16 | "destination_ips": [ 17 | "28.239.13.1/32", 18 | "28.239.14.0/24", 19 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 20 | ], 21 | "protocol": "tcp", 22 | "port": "80" 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /internal/cmd/firewall/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "firewall": { 3 | "id": 123, 4 | "name": "test", 5 | "labels": {}, 6 | "created": "2016-01-30T23:50:00Z", 7 | "rules": [ 8 | { 9 | "direction": "in", 10 | "source_ips": [], 11 | "destination_ips": [], 12 | "protocol": "tcp", 13 | "port": "22", 14 | "description": null 15 | } 16 | ], 17 | "applied_to": [ 18 | { 19 | "type": "server", 20 | "server": { 21 | "id": 1 22 | } 23 | } 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /internal/cmd/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "all", 13 | Short: "Commands that apply to all resources", 14 | Args: util.Validate, 15 | TraverseChildren: true, 16 | DisableFlagsInUseLine: true, 17 | } 18 | cmd.AddCommand( 19 | ListCmd.CobraCommand(s), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Welcome to the documentation for the **Hetzner Cloud CLI**. 4 | 5 | This documentation is written and organized following the [Diátaxis](https://diataxis.fr/) guidelines. Below you can find a high-level overview of where to look for certain things: 6 | 7 | - [Tutorials](tutorials) 8 | - [Guides](guides) 9 | - [Reference](reference) 10 | 11 | ## Getting help 12 | 13 | - 🐛 Report bugs using [our issue tracker](https://github.com/hetznercloud/cli/issues/new?template=bug.yaml). 14 | - 🙋 If you need help, reach us using the [Support Center](https://console.hetzner.com/support). 15 | -------------------------------------------------------------------------------- /internal/cmd/volume/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "volume": { 3 | "id": 123, 4 | "name": "test", 5 | "server": 123, 6 | "status": "available", 7 | "location": { 8 | "id": 0, 9 | "name": "fsn1", 10 | "description": "", 11 | "country": "", 12 | "city": "", 13 | "latitude": 0, 14 | "longitude": 0, 15 | "network_zone": "" 16 | }, 17 | "size": 20, 18 | "format": null, 19 | "protection": { 20 | "delete": true 21 | }, 22 | "labels": {}, 23 | "linux_device": "", 24 | "created": "2016-01-30T23:50:00Z" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /internal/cmd/servertype/server_type.go: -------------------------------------------------------------------------------- 1 | package servertype 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "server-type", 13 | Short: "View Server Types", 14 | Args: util.Validate, 15 | TraverseChildren: true, 16 | DisableFlagsInUseLine: true, 17 | } 18 | cmd.AddCommand( 19 | ListCmd.CobraCommand(s), 20 | DescribeCmd.CobraCommand(s), 21 | ) 22 | return cmd 23 | } 24 | -------------------------------------------------------------------------------- /internal/cmd/certificate/testdata/uploaded_create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "certificate": { 3 | "certificate": "", 4 | "created": "2020-08-24T12:00:00Z", 5 | "domain_names": null, 6 | "fingerprint": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00", 7 | "id": 123, 8 | "labels": { 9 | "key": "value" 10 | }, 11 | "name": "test", 12 | "not_valid_after": "2036-08-12T12:00:00Z", 13 | "not_valid_before": "2020-08-24T12:00:00Z", 14 | "status": null, 15 | "type": "uploaded", 16 | "used_by": [ 17 | { 18 | "id": 123, 19 | "type": "load_balancer" 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /internal/cmd/iso/iso.go: -------------------------------------------------------------------------------- 1 | package iso 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "iso", 13 | Aliases: []string{"isos"}, 14 | Short: "View ISOs", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | ListCmd.CobraCommand(s), 21 | DescribeCmd.CobraCommand(s), 22 | ) 23 | return cmd 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/floatingip/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "floating_ip": { 3 | "blocked": false, 4 | "created": "0001-01-01T00:00:00Z", 5 | "description": "", 6 | "dns_ptr": [], 7 | "home_location": { 8 | "city": "", 9 | "country": "", 10 | "description": "", 11 | "id": 0, 12 | "latitude": 0, 13 | "longitude": 0, 14 | "name": "", 15 | "network_zone": "" 16 | }, 17 | "id": 123, 18 | "ip": "127.0.0.1", 19 | "labels": {}, 20 | "name": "myFloatingIP", 21 | "protection": { 22 | "delete": false 23 | }, 24 | "server": 1, 25 | "type": "ipv4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /internal/cmd/util/deprecation.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dustin/go-humanize" 7 | 8 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 9 | ) 10 | 11 | func DescribeDeprecation(resource hcloud.Deprecatable) string { 12 | if !resource.IsDeprecated() { 13 | return "" 14 | } 15 | 16 | info := "Deprecation:\n" 17 | info += fmt.Sprintf(" Announced:\t%s (%s)\n", Datetime(resource.DeprecationAnnounced()), humanize.Time(resource.DeprecationAnnounced())) 18 | info += fmt.Sprintf(" Unavailable After:\t%s (%s)\n", Datetime(resource.UnavailableAfter()), humanize.Time(resource.UnavailableAfter())) 19 | 20 | return info 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/zone/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "zone": { 3 | "id": 123, 4 | "name": "example.com", 5 | "mode": "primary", 6 | "ttl": 600, 7 | "labels": { 8 | "foo": "bar" 9 | }, 10 | "primary_nameservers": null, 11 | "created": "2016-01-30T23:50:00Z", 12 | "protection": { 13 | "delete": false 14 | }, 15 | "status": "ok", 16 | "authoritative_nameservers": { 17 | "assigned": null, 18 | "delegated": null, 19 | "delegation_last_check": "1970-01-01T00:00:00Z", 20 | "delegation_status": "unknown" 21 | }, 22 | "record_count": 0, 23 | "registrar": "unknown" 24 | } 25 | } -------------------------------------------------------------------------------- /internal/testutil/terminal/terminal.go: -------------------------------------------------------------------------------- 1 | package terminal 2 | 3 | import ( 4 | "golang.org/x/term" 5 | 6 | "github.com/hetznercloud/cli/internal/ui" 7 | ) 8 | 9 | //go:generate mockgen -package terminal -destination zz_terminal_mock.go . Terminal 10 | 11 | type Terminal interface { 12 | StdoutIsTerminal() bool 13 | ReadPassword(fd int) ([]byte, error) 14 | } 15 | 16 | type DefaultTerminal struct{} 17 | 18 | func (DefaultTerminal) StdoutIsTerminal() bool { 19 | return ui.StdoutIsTerminal() 20 | } 21 | 22 | func (DefaultTerminal) ReadPassword(fd int) ([]byte, error) { 23 | return term.ReadPassword(fd) 24 | } 25 | 26 | var _ Terminal = DefaultTerminal{} 27 | -------------------------------------------------------------------------------- /internal/cmd/loadbalancertype/load_balancer_type.go: -------------------------------------------------------------------------------- 1 | package loadbalancertype 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "load-balancer-type", 13 | Short: "View Load Balancer Types", 14 | Args: util.Validate, 15 | TraverseChildren: true, 16 | DisableFlagsInUseLine: true, 17 | } 18 | cmd.AddCommand( 19 | DescribeCmd.CobraCommand(s), 20 | ListCmd.CobraCommand(s), 21 | ) 22 | return cmd 23 | } 24 | -------------------------------------------------------------------------------- /internal/cmd/location/location.go: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "location", 13 | Aliases: []string{"locations"}, 14 | Short: "View Locations", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | ListCmd.CobraCommand(s), 21 | DescribeCmd.CobraCommand(s), 22 | ) 23 | return cmd 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/datacenter/datacenter.go: -------------------------------------------------------------------------------- 1 | package datacenter 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "datacenter", 13 | Aliases: []string{"datacenters"}, 14 | Short: "View Datacenters", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | ListCmd.CobraCommand(s), 21 | DescribeCmd.CobraCommand(s), 22 | ) 23 | return cmd 24 | } 25 | -------------------------------------------------------------------------------- /internal/state/helpers.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/state/config" 9 | ) 10 | 11 | func Wrap(s State, f func(State, *cobra.Command, []string) error) func(*cobra.Command, []string) error { 12 | return func(cmd *cobra.Command, args []string) error { 13 | return f(s, cmd, args) 14 | } 15 | } 16 | 17 | func (c *state) EnsureToken(_ *cobra.Command, _ []string) error { 18 | token, err := config.OptionToken.Get(c.config) 19 | if err != nil { 20 | return err 21 | } 22 | if token == "" { 23 | return errors.New("no active context or token (see `hcloud context --help`)") 24 | } 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/releaser-pleaser.yml: -------------------------------------------------------------------------------- 1 | name: Releaser-pleaser 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request_target: 7 | types: 8 | - edited 9 | - labeled 10 | - unlabeled 11 | 12 | concurrency: 13 | group: releaser-pleaser 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | releaser-pleaser: 18 | # Do not run on forks. 19 | if: github.repository == 'hetznercloud/cli' 20 | 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: releaser-pleaser 24 | uses: apricote/releaser-pleaser@v0.7.1 25 | with: 26 | token: ${{ secrets.HCLOUD_BOT_TOKEN }} 27 | extra-files: | 28 | internal/version/version.go 29 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/subaccount/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "subaccount": { 3 | "id": 42, 4 | "username": "u1337-sub1", 5 | "home_directory": "my_backups/host01.my.company", 6 | "server": "u1337-sub1.your-storagebox.de", 7 | "access_settings": { 8 | "reachable_externally": false, 9 | "readonly": false, 10 | "samba_enabled": false, 11 | "ssh_enabled": false, 12 | "webdav_enabled": false 13 | }, 14 | "description": "host01 backup", 15 | "labels": { 16 | "environment": "prod", 17 | "example.com/my": "label", 18 | "just-a-key": "" 19 | }, 20 | "created": "2016-01-30T23:55:00Z", 21 | "storage_box": 42 22 | } 23 | } -------------------------------------------------------------------------------- /internal/cmd/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | "github.com/hetznercloud/cli/internal/version" 9 | ) 10 | 11 | func NewCommand(_ state.State) *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "version", 14 | Short: "Print version information", 15 | Args: util.Validate, 16 | DisableFlagsInUseLine: true, 17 | RunE: runVersion, 18 | } 19 | return cmd 20 | } 21 | 22 | func runVersion(cmd *cobra.Command, _ []string) error { 23 | cmd.Printf("hcloud %s\n", version.Version) 24 | return nil 25 | } 26 | -------------------------------------------------------------------------------- /internal/cmd/context/context.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "context", 13 | Short: "Manage contexts", 14 | Args: util.Validate, 15 | TraverseChildren: true, 16 | DisableFlagsInUseLine: true, 17 | } 18 | cmd.AddCommand( 19 | NewCreateCommand(s), 20 | NewActiveCommand(s), 21 | NewUnsetCommand(s), 22 | NewUseCommand(s), 23 | NewDeleteCommand(s), 24 | NewListCommand(s), 25 | NewRenameCommand(s), 26 | ) 27 | return cmd 28 | } 29 | -------------------------------------------------------------------------------- /internal/cmd/certificate/testdata/managed_create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "certificate": { 3 | "certificate": "certificate data placeholder", 4 | "created": "2020-08-24T12:00:00Z", 5 | "domain_names": [ 6 | "example.com" 7 | ], 8 | "fingerprint": "fingerprint placeholder", 9 | "id": 123, 10 | "labels": { 11 | "key": "value" 12 | }, 13 | "name": "test", 14 | "not_valid_after": "2036-08-12T12:00:00Z", 15 | "not_valid_before": "2020-08-24T12:00:00Z", 16 | "status": { 17 | "issuance": "completed", 18 | "renewal": "unavailable" 19 | }, 20 | "type": "managed", 21 | "used_by": [ 22 | { 23 | "id": 123, 24 | "type": "load_balancer" 25 | } 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /internal/state/command_helpers.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 9 | ) 10 | 11 | //go:generate mockgen -package state -destination zz_command_helper_mock.go . ActionWaiter,TokenEnsurer 12 | 13 | type ActionWaiter interface { 14 | WaitForActions(context.Context, *cobra.Command, ...*hcloud.Action) error 15 | } 16 | 17 | type TokenEnsurer interface { 18 | EnsureToken(cmd *cobra.Command, args []string) error 19 | } 20 | 21 | func WrapCtx( 22 | ctx context.Context, 23 | fn func(context.Context, *cobra.Command, []string) error, 24 | ) func(*cobra.Command, []string) error { 25 | return func(cmd *cobra.Command, args []string) error { 26 | return fn(ctx, cmd, args) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/e2e/rules_file.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Allow port 80", 4 | "direction": "in", 5 | "port": "80", 6 | "protocol": "tcp", 7 | "source_ips": [ 8 | "28.239.13.1/32", 9 | "28.239.14.0/24", 10 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 11 | ] 12 | }, 13 | { 14 | "description": "Allow port 443", 15 | "direction": "in", 16 | "port": "443", 17 | "protocol": "tcp", 18 | "source_ips": [ 19 | "0.0.0.0/0", 20 | "::/0" 21 | ] 22 | }, 23 | { 24 | "direction": "out", 25 | "source_ips": [], 26 | "destination_ips": [ 27 | "28.239.13.1/32", 28 | "28.239.14.0/24", 29 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 30 | ], 31 | "protocol": "tcp", 32 | "port": "80" 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /internal/cmd/util/idna.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "golang.org/x/net/idna" 4 | 5 | // DisplayZoneName prepares the zone name for user display by converting the ASCII punycode encoding to Unicode. 6 | func DisplayZoneName(zoneName string) string { 7 | display, err := idna.Display.ToUnicode(zoneName) 8 | if err != nil { 9 | // Let's just show the zoneName as returned by the API, better than throwing an error. 10 | return zoneName 11 | } 12 | return display 13 | } 14 | 15 | // ParseZoneIDOrName converts user input for the zone name into an API compatible form. We want to accept Unicode and 16 | // Punycode/ASCII variants from the user, but the API always expects Punycode/ASCII. 17 | func ParseZoneIDOrName(zoneIDOrName string) (string, error) { 18 | return idna.Punycode.ToASCII(zoneIDOrName) 19 | } 20 | -------------------------------------------------------------------------------- /internal/cmd/storageboxtype/storage_box_type.go: -------------------------------------------------------------------------------- 1 | package storageboxtype 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/experimental" 7 | "github.com/hetznercloud/cli/internal/cmd/util" 8 | "github.com/hetznercloud/cli/internal/state" 9 | ) 10 | 11 | func NewCommand(s state.State) *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "storage-box-type", 14 | Aliases: []string{"storage-box-types"}, 15 | Short: "View Storage Box Types", 16 | Args: util.Validate, 17 | TraverseChildren: true, 18 | DisableFlagsInUseLine: true, 19 | } 20 | cmd.AddCommand( 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | ) 24 | return experimental.StorageBoxes(s, cmd) 25 | } 26 | -------------------------------------------------------------------------------- /internal/cmd/firewall/testdata/rules.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Allow port 80", 4 | "direction": "in", 5 | "port": "80", 6 | "protocol": "tcp", 7 | "source_ips": [ 8 | "28.239.13.1/32", 9 | "28.239.14.0/24", 10 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 11 | ] 12 | }, 13 | { 14 | "description": "Allow port 443", 15 | "direction": "in", 16 | "port": "443", 17 | "protocol": "tcp", 18 | "source_ips": [ 19 | "0.0.0.0/0", 20 | "::/0" 21 | ] 22 | }, 23 | { 24 | "direction": "out", 25 | "source_ips": [], 26 | "destination_ips": [ 27 | "28.239.13.1/32", 28 | "28.239.14.0/24", 29 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 30 | ], 31 | "protocol": "tcp", 32 | "port": "80" 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | env: 9 | GOTOOLCHAIN: local 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v6 17 | 18 | - name: Set up tools 19 | uses: jdx/mise-action@v3 20 | with: 21 | version: 2025.12.12 # renovate: datasource=github-releases depName=jdx/mise 22 | 23 | - name: Run GoReleaser 24 | run: goreleaser release --clean --snapshot --skip=sign 25 | 26 | - uses: actions/upload-artifact@v6 27 | with: 28 | name: Preview Binaries 29 | path: dist/hcloud-*/hcloud 30 | 31 | - name: Check for release errors 32 | run: scripts/check-release-error.sh 33 | -------------------------------------------------------------------------------- /internal/ui/progress.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | type ProgressGroup interface { 8 | Add(message string, resources string) Progress 9 | Start() error 10 | Stop() error 11 | } 12 | 13 | func NewProgressGroup(output io.Writer) ProgressGroup { 14 | if StdoutIsTerminal() && TerminalWidth() > 80 { 15 | return newTerminalProgressGroup(output) 16 | } 17 | return newScriptProgressGroup(output) 18 | } 19 | 20 | type Progress interface { 21 | Start() 22 | SetCurrent(value int) 23 | SetSuccess() 24 | SetError() 25 | } 26 | 27 | func NewProgress(output io.Writer, message string, resources string) Progress { 28 | if StdoutIsTerminal() && TerminalWidth() > 80 { 29 | return newTerminalProgress(output, message, resources) 30 | } 31 | return newScriptProgress(output, message, resources) 32 | } 33 | -------------------------------------------------------------------------------- /internal/cmd/server/texts.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 7 | "github.com/hetznercloud/hcloud-go/v2/hcloud/exp/deprecationutil" 8 | ) 9 | 10 | const ChangeDeprecatedServerTypeMessage = (`Existing servers of that plan will ` + 11 | `continue to work as before and no action is required on your part. ` + 12 | `It is possible to migrate this Server to another Server Type by using ` + 13 | `the "hcloud server change-type" command.`) 14 | 15 | func deprecatedServerTypeWarning(serverType *hcloud.ServerType, locationName string) string { 16 | message, _ := deprecationutil.ServerTypeMessage(serverType, locationName) 17 | if message == "" { 18 | return "" 19 | } 20 | 21 | return fmt.Sprintf("Attention: %s. %s\n\n", message, ChangeDeprecatedServerTypeMessage) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/hcloud/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/hetznercloud/cli/internal/cli" 8 | "github.com/hetznercloud/cli/internal/cmd/util" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/cli/internal/state/config" 11 | ) 12 | 13 | func init() { 14 | log.SetFlags(0) 15 | log.SetPrefix("hcloud: ") 16 | log.SetOutput(os.Stderr) 17 | } 18 | 19 | func main() { 20 | cfg := config.New() 21 | if err := cfg.Read(nil); err != nil { 22 | log.Fatalf("unable to read config file \"%s\": %s\n", cfg.Path(), err) 23 | } 24 | 25 | s, err := state.New(cfg) 26 | if err != nil { 27 | log.Fatalln(err) 28 | } 29 | 30 | rootCommand := cli.NewRootCommand(s) 31 | 32 | if err := rootCommand.Execute(); err != nil { 33 | log.Fatalln(util.FormatHcloudError(err)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /internal/cmd/sshkey/sshkey.go: -------------------------------------------------------------------------------- 1 | package sshkey 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "ssh-key", 13 | Aliases: []string{"ssh-keys"}, 14 | Short: "Manage SSH Keys", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | ListCmd.CobraCommand(s), 21 | CreateCmd.CobraCommand(s), 22 | UpdateCmd.CobraCommand(s), 23 | DeleteCmd.CobraCommand(s), 24 | DescribeCmd.CobraCommand(s), 25 | LabelCmds.AddCobraCommand(s), 26 | LabelCmds.RemoveCobraCommand(s), 27 | ) 28 | return cmd 29 | } 30 | -------------------------------------------------------------------------------- /internal/cmd/server/set_rdns.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/base" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | "github.com/hetznercloud/cli/internal/state" 11 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 12 | ) 13 | 14 | var SetRDNSCmd = base.SetRdnsCmd[*hcloud.Server]{ 15 | ResourceNameSingular: "Server", 16 | ShortDescription: "Change reverse DNS of a Server", 17 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, 18 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Server, *hcloud.Response, error) { 19 | return s.Client().Server().Get(s, idOrName) 20 | }, 21 | GetDefaultIP: func(server *hcloud.Server) net.IP { 22 | return server.PublicNet.IPv4.IP 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/floatingip/set_rdns.go: -------------------------------------------------------------------------------- 1 | package floatingip 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/base" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | "github.com/hetznercloud/cli/internal/state" 11 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 12 | ) 13 | 14 | var SetRDNSCmd = base.SetRdnsCmd[*hcloud.FloatingIP]{ 15 | ResourceNameSingular: "Floating IP", 16 | ShortDescription: "Change reverse DNS of a Floating IP", 17 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, 18 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.FloatingIP, *hcloud.Response, error) { 19 | return s.Client().FloatingIP().Get(s, idOrName) 20 | }, 21 | GetDefaultIP: func(floatingIP *hcloud.FloatingIP) net.IP { 22 | return floatingIP.IP 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/context/unset.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/cmpl" 7 | "github.com/hetznercloud/cli/internal/cmd/util" 8 | "github.com/hetznercloud/cli/internal/state" 9 | ) 10 | 11 | func NewUnsetCommand(s state.State) *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "unset", 14 | Short: "Unset used context", 15 | Args: util.Validate, 16 | ValidArgsFunction: cmpl.SuggestNothing(), 17 | TraverseChildren: true, 18 | DisableFlagsInUseLine: true, 19 | SilenceUsage: true, 20 | RunE: state.Wrap(s, runUnset), 21 | } 22 | return cmd 23 | } 24 | 25 | func runUnset(s state.State, _ *cobra.Command, _ []string) error { 26 | cfg := s.Config() 27 | cfg.SetActiveContext(nil) 28 | return cfg.Write(nil) 29 | } 30 | -------------------------------------------------------------------------------- /internal/cmd/placementgroup/placementgroup.go: -------------------------------------------------------------------------------- 1 | package placementgroup 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "placement-group", 13 | Aliases: []string{"placement-groups"}, 14 | Short: "Manage Placement Groups", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | CreateCmd.CobraCommand(s), 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | UpdateCmd.CobraCommand(s), 24 | DeleteCmd.CobraCommand(s), 25 | LabelCmds.AddCobraCommand(s), 26 | LabelCmds.RemoveCobraCommand(s), 27 | ) 28 | return cmd 29 | } 30 | -------------------------------------------------------------------------------- /internal/cmd/primaryip/set_rdns.go: -------------------------------------------------------------------------------- 1 | package primaryip 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/base" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | "github.com/hetznercloud/cli/internal/state" 11 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 12 | ) 13 | 14 | var SetRDNSCmd = base.SetRdnsCmd[*hcloud.PrimaryIP]{ 15 | ResourceNameSingular: "Primary IP", 16 | ShortDescription: "Change reverse DNS of a Primary IP", 17 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names(false, false, nil) }, 18 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.PrimaryIP, *hcloud.Response, error) { 19 | return s.Client().PrimaryIP().Get(s, idOrName) 20 | }, 21 | GetDefaultIP: func(primaryIP *hcloud.PrimaryIP) net.IP { 22 | return primaryIP.IP 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/certificate/certificate.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "certificate", 13 | Aliases: []string{"certificates"}, 14 | Short: "Manage Certificates", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | cmd.AddCommand( 20 | ListCmd.CobraCommand(s), 21 | CreateCmd.CobraCommand(s), 22 | UpdateCmd.CobraCommand(s), 23 | LabelCmds.AddCobraCommand(s), 24 | LabelCmds.RemoveCobraCommand(s), 25 | DeleteCmd.CobraCommand(s), 26 | DescribeCmd.CobraCommand(s), 27 | RetryCmd.CobraCommand(s), 28 | ) 29 | 30 | return cmd 31 | } 32 | -------------------------------------------------------------------------------- /internal/cmd/loadbalancer/set_rdns.go: -------------------------------------------------------------------------------- 1 | package loadbalancer 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/base" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | "github.com/hetznercloud/cli/internal/state" 11 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 12 | ) 13 | 14 | var SetRDNSCmd = base.SetRdnsCmd[*hcloud.LoadBalancer]{ 15 | ResourceNameSingular: "Load Balancer", 16 | ShortDescription: "Change reverse DNS of a Load Balancer", 17 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, 18 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.LoadBalancer, *hcloud.Response, error) { 19 | return s.Client().LoadBalancer().Get(s, idOrName) 20 | }, 21 | GetDefaultIP: func(loadBalancer *hcloud.LoadBalancer) net.IP { 22 | return loadBalancer.PublicNet.IPv4.IP 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/volume/delete.go: -------------------------------------------------------------------------------- 1 | package volume 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.Volume]{ 13 | ResourceNameSingular: "Volume", 14 | ResourceNamePlural: "Volumes", 15 | ShortDescription: "Delete a Volume", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Volume, *hcloud.Response, error) { 18 | return s.Client().Volume().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, volume *hcloud.Volume) (*hcloud.Action, error) { 21 | _, err := s.Client().Volume().Delete(s, volume) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/sshkey/delete.go: -------------------------------------------------------------------------------- 1 | package sshkey 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.SSHKey]{ 13 | ResourceNameSingular: "SSH Key", 14 | ResourceNamePlural: "SSH Keys", 15 | ShortDescription: "Delete an SSH Key", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.SSHKey, *hcloud.Response, error) { 18 | return s.Client().SSHKey().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, sshKey *hcloud.SSHKey) (*hcloud.Action, error) { 21 | _, err := s.Client().SSHKey().Delete(s, sshKey) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/network/delete.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.Network]{ 13 | ResourceNameSingular: "Network", 14 | ResourceNamePlural: "Networks", 15 | ShortDescription: "Delete a network", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Network().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Network, *hcloud.Response, error) { 18 | return s.Client().Network().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, network *hcloud.Network) (*hcloud.Action, error) { 21 | _, err := s.Client().Network().Delete(s, network) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/firewall/delete.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.Firewall]{ 13 | ResourceNameSingular: "Firewall", 14 | ResourceNamePlural: "Firewalls", 15 | ShortDescription: "Delete a Firewall", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Firewall, *hcloud.Response, error) { 18 | return s.Client().Firewall().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, firewall *hcloud.Firewall) (*hcloud.Action, error) { 21 | _, err := s.Client().Firewall().Delete(s, firewall) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/snapshot/snapshot.go: -------------------------------------------------------------------------------- 1 | package snapshot 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/experimental" 7 | "github.com/hetznercloud/cli/internal/cmd/util" 8 | "github.com/hetznercloud/cli/internal/state" 9 | ) 10 | 11 | func NewCommand(s state.State) *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "snapshot", 14 | Aliases: []string{"snapshots"}, 15 | Short: "Manage Storage Box Snapshots", 16 | Args: util.Validate, 17 | TraverseChildren: true, 18 | DisableFlagsInUseLine: true, 19 | } 20 | cmd.AddCommand( 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | CreateCmd.CobraCommand(s), 24 | UpdateCmd.CobraCommand(s), 25 | LabelCmds.AddCobraCommand(s), 26 | LabelCmds.RemoveCobraCommand(s), 27 | DeleteCmd.CobraCommand(s), 28 | ) 29 | return experimental.StorageBoxes(s, cmd) 30 | } 31 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/snapshot/cmpl.go: -------------------------------------------------------------------------------- 1 | package snapshot 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/cmpl" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | ) 11 | 12 | func SuggestSnapshots(client hcapi2.Client) cobra.CompletionFunc { 13 | return cmpl.SuggestCandidatesCtx(func(cmd *cobra.Command, args []string) []string { 14 | if len(args) == 0 { 15 | return nil 16 | } 17 | 18 | storageBox, _, err := client.StorageBox().Get(cmd.Context(), args[0]) 19 | if err != nil || storageBox == nil { 20 | return nil 21 | } 22 | 23 | snapshots, err := client.StorageBox().AllSnapshots(context.Background(), storageBox) 24 | if err != nil { 25 | return nil 26 | } 27 | 28 | snapshotNames := make([]string, 0, len(snapshots)) 29 | for _, snapshot := range snapshots { 30 | snapshotNames = append(snapshotNames, snapshot.Name) 31 | } 32 | return snapshotNames 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /internal/cmd/context/active.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/hetznercloud/cli/internal/cmd/util" 10 | "github.com/hetznercloud/cli/internal/state" 11 | ) 12 | 13 | func NewActiveCommand(s state.State) *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "active", 16 | Short: "Show active context", 17 | Args: util.Validate, 18 | TraverseChildren: true, 19 | DisableFlagsInUseLine: true, 20 | RunE: state.Wrap(s, runActive), 21 | } 22 | return cmd 23 | } 24 | 25 | func runActive(s state.State, cmd *cobra.Command, _ []string) error { 26 | if os.Getenv("HCLOUD_TOKEN") != "" { 27 | _, _ = fmt.Fprintln(os.Stderr, "Warning: HCLOUD_TOKEN is set. The active context's token will have no effect.") 28 | } 29 | if ctx := s.Config().ActiveContext(); !util.IsNil(ctx) { 30 | cmd.Println(ctx.Name()) 31 | } 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /internal/cmd/floatingip/delete.go: -------------------------------------------------------------------------------- 1 | package floatingip 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.FloatingIP]{ 13 | ResourceNameSingular: "Floating IP", 14 | ResourceNamePlural: "Floating IPs", 15 | ShortDescription: "Delete a Floating IP", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.FloatingIP, *hcloud.Response, error) { 18 | return s.Client().FloatingIP().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, floatingIP *hcloud.FloatingIP) (*hcloud.Action, error) { 21 | _, err := s.Client().FloatingIP().Delete(s, floatingIP) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/certificate/delete.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.Certificate]{ 13 | ResourceNameSingular: "Certificate", 14 | ResourceNamePlural: "Certificates", 15 | ShortDescription: "Delete a Certificate", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Certificate, *hcloud.Response, error) { 18 | return s.Client().Certificate().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, certificate *hcloud.Certificate) (*hcloud.Action, error) { 21 | _, err := s.Client().Certificate().Delete(s, certificate) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/image/image.go: -------------------------------------------------------------------------------- 1 | package image 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "image", 13 | Aliases: []string{"images"}, 14 | Short: "Manage Images", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | 20 | util.AddGroup(cmd, "general", "General", 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | DeleteCmd.CobraCommand(s), 24 | UpdateCmd.CobraCommand(s), 25 | LabelCmds.AddCobraCommand(s), 26 | LabelCmds.RemoveCobraCommand(s), 27 | ) 28 | 29 | util.AddGroup(cmd, "protection", "Protection", 30 | ChangeProtectionCmds.EnableCobraCommand(s), 31 | ChangeProtectionCmds.DisableCobraCommand(s), 32 | ) 33 | return cmd 34 | } 35 | -------------------------------------------------------------------------------- /internal/cmd/primaryip/delete.go: -------------------------------------------------------------------------------- 1 | package primaryip 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.PrimaryIP]{ 13 | ResourceNameSingular: "Primary IP", 14 | ResourceNamePlural: "Primary IPs", 15 | ShortDescription: "Delete a Primary IP", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.PrimaryIP().Names(false, false, nil) }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.PrimaryIP, *hcloud.Response, error) { 18 | return s.Client().PrimaryIP().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, primaryIP *hcloud.PrimaryIP) (*hcloud.Action, error) { 21 | _, err := s.Client().PrimaryIP().Delete(s, primaryIP) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/primaryip/testdata/create_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "primary_ip": { 3 | "assignee_id": 1, 4 | "assignee_type": "server", 5 | "auto_delete": true, 6 | "blocked": false, 7 | "created": "2016-01-30T23:50:00Z", 8 | "datacenter": { 9 | "description": "", 10 | "id": 1, 11 | "location": { 12 | "city": "", 13 | "country": "", 14 | "description": "", 15 | "id": 1, 16 | "latitude": 0, 17 | "longitude": 0, 18 | "name": "fsn1", 19 | "network_zone": "" 20 | }, 21 | "name": "fsn1-dc14", 22 | "server_types": { 23 | "available": null, 24 | "available_for_migration": null, 25 | "supported": null 26 | } 27 | }, 28 | "dns_ptr": [], 29 | "id": 1, 30 | "ip": "192.168.2.1", 31 | "labels": { 32 | "foo": "bar" 33 | }, 34 | "name": "my-ip", 35 | "protection": { 36 | "delete": false 37 | }, 38 | "type": "ipv4" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/loadbalancer/delete.go: -------------------------------------------------------------------------------- 1 | package loadbalancer 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.LoadBalancer]{ 13 | ResourceNameSingular: "Load Balancer", 14 | ResourceNamePlural: "Load Balancers", 15 | ShortDescription: "Delete a Load Balancer", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.LoadBalancer().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.LoadBalancer, *hcloud.Response, error) { 18 | return s.Client().LoadBalancer().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, loadBalancer *hcloud.LoadBalancer) (*hcloud.Action, error) { 21 | _, err := s.Client().LoadBalancer().Delete(s, loadBalancer) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/server/delete.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.Server]{ 13 | ResourceNameSingular: "Server", 14 | ResourceNamePlural: "Servers", 15 | ShortDescription: "Delete a server", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Server, *hcloud.Response, error) { 18 | return s.Client().Server().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, server *hcloud.Server) (*hcloud.Action, error) { 21 | result, _, err := s.Client().Server().DeleteWithResult(s, server) 22 | if err != nil { 23 | return nil, err 24 | } 25 | return result.Action, nil 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/subaccount/cmpl.go: -------------------------------------------------------------------------------- 1 | package subaccount 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/cmpl" 9 | "github.com/hetznercloud/cli/internal/hcapi2" 10 | ) 11 | 12 | func SuggestSubaccounts(client hcapi2.Client) cobra.CompletionFunc { 13 | return cmpl.SuggestCandidatesCtx(func(cmd *cobra.Command, args []string) []string { 14 | if len(args) == 0 { 15 | return nil 16 | } 17 | 18 | storageBox, _, err := client.StorageBox().Get(cmd.Context(), args[0]) 19 | if err != nil || storageBox == nil { 20 | return nil 21 | } 22 | 23 | subaccounts, err := client.StorageBox().AllSubaccounts(context.Background(), storageBox) 24 | if err != nil { 25 | return nil 26 | } 27 | 28 | subaccountUsernames := make([]string, 0, len(subaccounts)) 29 | for _, subaccount := range subaccounts { 30 | subaccountUsernames = append(subaccountUsernames, subaccount.Username) 31 | } 32 | return subaccountUsernames 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/subaccount/subaccount.go: -------------------------------------------------------------------------------- 1 | package subaccount 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/experimental" 7 | "github.com/hetznercloud/cli/internal/cmd/util" 8 | "github.com/hetznercloud/cli/internal/state" 9 | ) 10 | 11 | func NewCommand(s state.State) *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "subaccount", 14 | Aliases: []string{"subaccounts"}, 15 | Short: "Manage Storage Box Subaccounts", 16 | Args: util.Validate, 17 | TraverseChildren: true, 18 | DisableFlagsInUseLine: true, 19 | } 20 | cmd.AddCommand( 21 | ListCmd.CobraCommand(s), 22 | CreateCmd.CobraCommand(s), 23 | DeleteCmd.CobraCommand(s), 24 | UpdateCmd.CobraCommand(s), 25 | DescribeCmd.CobraCommand(s), 26 | ResetPasswordCmd.CobraCommand(s), 27 | UpdateAccessSettingsCmd.CobraCommand(s), 28 | ChangeHomeDirectoryCmd.CobraCommand(s), 29 | ) 30 | return experimental.StorageBoxes(s, cmd) 31 | } 32 | -------------------------------------------------------------------------------- /internal/hcapi2/iso.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | import ( 4 | "context" 5 | "strconv" 6 | 7 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 8 | ) 9 | 10 | // ISOClient embeds the Hetzner Cloud iso client and provides some 11 | // additional helper functions. 12 | type ISOClient interface { 13 | hcloud.IISOClient 14 | Names() []string 15 | } 16 | 17 | func NewISOClient(client hcloud.IISOClient) ISOClient { 18 | return &isoClient{ 19 | IISOClient: client, 20 | } 21 | } 22 | 23 | type isoClient struct { 24 | hcloud.IISOClient 25 | } 26 | 27 | // Names obtains a list of available data centers. It returns nil if 28 | // iso names could not be fetched. 29 | func (c *isoClient) Names() []string { 30 | isos, err := c.All(context.Background()) 31 | if err != nil || len(isos) == 0 { 32 | return nil 33 | } 34 | names := make([]string, len(isos)) 35 | for i, iso := range isos { 36 | name := iso.Name 37 | if name == "" { 38 | name = strconv.FormatInt(iso.ID, 10) 39 | } 40 | names[i] = name 41 | } 42 | return names 43 | } 44 | -------------------------------------------------------------------------------- /internal/cmd/placementgroup/delete.go: -------------------------------------------------------------------------------- 1 | package placementgroup 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/hcapi2" 8 | "github.com/hetznercloud/cli/internal/state" 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | var DeleteCmd = base.DeleteCmd[*hcloud.PlacementGroup]{ 13 | ResourceNameSingular: "Placement Group", 14 | ResourceNamePlural: "Placement Groups", 15 | ShortDescription: "Delete a Placement Group", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.PlacementGroup().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.PlacementGroup, *hcloud.Response, error) { 18 | return s.Client().PlacementGroup().Get(s, idOrName) 19 | }, 20 | Delete: func(s state.State, _ *cobra.Command, placementGroup *hcloud.PlacementGroup) (*hcloud.Action, error) { 21 | _, err := s.Client().PlacementGroup().Delete(s, placementGroup) 22 | return nil, err 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /internal/cmd/server/update_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.ServerClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.Server{ID: 123}, nil, nil) 25 | fx.Client.ServerClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.Server{ID: 123}, hcloud.ServerUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Server 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/volume/update_test.go: -------------------------------------------------------------------------------- 1 | package volume_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/volume" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := volume.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.VolumeClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.Volume{ID: 123}, nil, nil) 25 | fx.Client.VolumeClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.Volume{ID: 123}, hcloud.VolumeUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Volume 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/sshkey/update_test.go: -------------------------------------------------------------------------------- 1 | package sshkey_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/sshkey" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := sshkey.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.SSHKeyClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.SSHKey{ID: 123}, nil, nil) 25 | fx.Client.SSHKeyClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.SSHKey{ID: 123}, hcloud.SSHKeyUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "SSH Key 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/network/update_test.go: -------------------------------------------------------------------------------- 1 | package network_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/network" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := network.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.NetworkClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.Network{ID: 123}, nil, nil) 25 | fx.Client.NetworkClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.Network{ID: 123}, hcloud.NetworkUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Network 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/firewall/update_test.go: -------------------------------------------------------------------------------- 1 | package firewall_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/firewall" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := firewall.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.FirewallClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.Firewall{ID: 123}, nil, nil) 25 | fx.Client.FirewallClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.Firewall{ID: 123}, hcloud.FirewallUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Firewall 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/delete.go: -------------------------------------------------------------------------------- 1 | package storagebox 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/base" 7 | "github.com/hetznercloud/cli/internal/cmd/experimental" 8 | "github.com/hetznercloud/cli/internal/hcapi2" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 11 | ) 12 | 13 | var DeleteCmd = base.DeleteCmd[*hcloud.StorageBox]{ 14 | ResourceNameSingular: "Storage Box", 15 | ResourceNamePlural: "Storage Boxes", 16 | ShortDescription: "Delete a Storage Box", 17 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.StorageBox().Names }, 18 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.StorageBox, *hcloud.Response, error) { 19 | return s.Client().StorageBox().Get(s, idOrName) 20 | }, 21 | Delete: func(s state.State, _ *cobra.Command, storageBox *hcloud.StorageBox) (*hcloud.Action, error) { 22 | result, _, err := s.Client().StorageBox().Delete(s, storageBox) 23 | return result.Action, err 24 | }, 25 | Experimental: experimental.StorageBoxes, 26 | } 27 | -------------------------------------------------------------------------------- /internal/cmd/certificate/update_test.go: -------------------------------------------------------------------------------- 1 | package certificate_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/certificate" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := certificate.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.CertificateClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.Certificate{ID: 123}, nil, nil) 25 | fx.Client.CertificateClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.Certificate{ID: 123}, hcloud.CertificateUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Certificate 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/image/delete.go: -------------------------------------------------------------------------------- 1 | package image 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/hetznercloud/cli/internal/cmd/base" 10 | "github.com/hetznercloud/cli/internal/hcapi2" 11 | "github.com/hetznercloud/cli/internal/state" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | var DeleteCmd = base.DeleteCmd[*hcloud.Image]{ 16 | ResourceNameSingular: "Image", 17 | ResourceNamePlural: "Images", 18 | ShortDescription: "Delete an Image", 19 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names }, 20 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Image, *hcloud.Response, error) { 21 | id, err := strconv.ParseInt(idOrName, 10, 64) 22 | if err != nil { 23 | return nil, nil, fmt.Errorf("invalid snapshot or backup ID %q", idOrName) 24 | } 25 | return s.Client().Image().GetByID(s, id) 26 | }, 27 | Delete: func(s state.State, _ *cobra.Command, image *hcloud.Image) (*hcloud.Action, error) { 28 | _, err := s.Client().Image().Delete(s, image) 29 | return nil, err 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /internal/hcapi2/datacenter.go: -------------------------------------------------------------------------------- 1 | package hcapi2 2 | 3 | import ( 4 | "context" 5 | "strconv" 6 | 7 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 8 | ) 9 | 10 | // DatacenterClient embeds the Hetzner Cloud DataCenter client and provides some 11 | // additional helper functions. 12 | type DatacenterClient interface { 13 | hcloud.IDatacenterClient 14 | Names() []string 15 | } 16 | 17 | func NewDatacenterClient(client hcloud.IDatacenterClient) DatacenterClient { 18 | return &datacenterClient{ 19 | IDatacenterClient: client, 20 | } 21 | } 22 | 23 | type datacenterClient struct { 24 | hcloud.IDatacenterClient 25 | } 26 | 27 | // Names obtains a list of available data centers. It returns nil if 28 | // data center names could not be fetched. 29 | func (c *datacenterClient) Names() []string { 30 | dcs, err := c.All(context.Background()) 31 | if err != nil || len(dcs) == 0 { 32 | return nil 33 | } 34 | names := make([]string, len(dcs)) 35 | for i, dc := range dcs { 36 | name := dc.Name 37 | if name == "" { 38 | name = strconv.FormatInt(dc.ID, 10) 39 | } 40 | names[i] = name 41 | } 42 | return names 43 | } 44 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_version.md: -------------------------------------------------------------------------------- 1 | ## hcloud version 2 | 3 | Print version information 4 | 5 | ``` 6 | hcloud version 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for version 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud](hcloud.md) - Hetzner Cloud CLI 32 | -------------------------------------------------------------------------------- /internal/cmd/loadbalancer/update_test.go: -------------------------------------------------------------------------------- 1 | package loadbalancer_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/loadbalancer" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := loadbalancer.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.LoadBalancerClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.LoadBalancer{ID: 123}, nil, nil) 25 | fx.Client.LoadBalancerClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.LoadBalancer{ID: 123}, hcloud.LoadBalancerUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Load Balancer 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/update_test.go: -------------------------------------------------------------------------------- 1 | package storagebox_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/storagebox" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := storagebox.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.StorageBoxClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.StorageBox{ID: 123}, nil, nil) 25 | fx.Client.StorageBoxClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.StorageBox{ID: 123}, hcloud.StorageBoxUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Storage Box 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Equal(t, ExperimentalWarning, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /internal/ui/actions.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/fatih/color" 8 | 9 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 10 | ) 11 | 12 | func ActionMessage(action *hcloud.Action) string { 13 | return fmt.Sprintf("Waiting for %s", color.New(color.Bold).Sprint(action.Command)) 14 | } 15 | 16 | // FakeActionMessage returns the initial value with a unused color to grow the string 17 | // size. 18 | // 19 | // Because the [ActionMessage] function adds 1 color to the returned string. We add the 20 | // same amount of colors to the [FakeActionMessage], to make sure the padding is 21 | // correct. 22 | func FakeActionMessage(value string) string { 23 | return color.New(color.Bold).Sprint("") + value 24 | } 25 | 26 | func ActionResourcesMessage(resources ...*hcloud.ActionResource) string { 27 | if len(resources) == 0 { 28 | return "" 29 | } 30 | 31 | items := make([]string, 0, len(resources)) 32 | for _, resource := range resources { 33 | items = append(items, fmt.Sprintf("%s: %d", resource.Type, resource.ID)) 34 | } 35 | 36 | return fmt.Sprintf("(%v)", strings.Join(items, ", ")) 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Hetzner Cloud GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_context_unset.md: -------------------------------------------------------------------------------- 1 | ## hcloud context unset 2 | 3 | Unset used context 4 | 5 | ``` 6 | hcloud context unset 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for unset 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud context](hcloud_context.md) - Manage contexts 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_context_use.md: -------------------------------------------------------------------------------- 1 | ## hcloud context use 2 | 3 | Use a context 4 | 5 | ``` 6 | hcloud context use 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for use 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud context](hcloud_context.md) - Manage contexts 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_image_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud image delete 2 | 3 | Delete an Image 4 | 5 | ``` 6 | hcloud image delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud image](hcloud_image.md) - Manage Images 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_context_active.md: -------------------------------------------------------------------------------- 1 | ## hcloud context active 2 | 3 | Show active context 4 | 5 | ``` 6 | hcloud context active 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for active 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud context](hcloud_context.md) - Manage contexts 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_reboot.md: -------------------------------------------------------------------------------- 1 | ## hcloud server reboot 2 | 3 | Reboot a server 4 | 5 | ``` 6 | hcloud server reboot 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for reboot 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_detach.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume detach 2 | 3 | Detach a Volume 4 | 5 | ``` 6 | hcloud volume detach 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for detach 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 32 | -------------------------------------------------------------------------------- /internal/cmd/placementgroup/update_test.go: -------------------------------------------------------------------------------- 1 | package placementgroup_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/placementgroup" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUpdateName(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := placementgroup.UpdateCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.PlacementGroupClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.PlacementGroup{ID: 123}, nil, nil) 25 | fx.Client.PlacementGroupClient.EXPECT(). 26 | Update(gomock.Any(), &hcloud.PlacementGroup{ID: 123}, hcloud.PlacementGroupUpdateOpts{ 27 | Name: "new-name", 28 | }) 29 | 30 | out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) 31 | 32 | expOut := "Placement Group 123 updated\n" 33 | 34 | require.NoError(t, err) 35 | assert.Empty(t, errOut) 36 | assert.Equal(t, expOut, out) 37 | } 38 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud server delete 2 | 3 | Delete a server 4 | 5 | ``` 6 | hcloud server delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_poweron.md: -------------------------------------------------------------------------------- 1 | ## hcloud server poweron 2 | 3 | Poweron a server 4 | 5 | ``` 6 | hcloud server poweron 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for poweron 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_reset.md: -------------------------------------------------------------------------------- 1 | ## hcloud server reset 2 | 3 | Reset a Server 4 | 5 | ``` 6 | hcloud server reset [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for reset 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume delete 2 | 3 | Delete a Volume 4 | 5 | ``` 6 | hcloud volume delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 32 | -------------------------------------------------------------------------------- /internal/cmd/volume/detach_test.go: -------------------------------------------------------------------------------- 1 | package volume_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/volume" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDetach(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := volume.DetachCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | v := &hcloud.Volume{ID: 123} 23 | 24 | fx.Client.VolumeClient.EXPECT(). 25 | Get(gomock.Any(), "123"). 26 | Return(v, nil, nil) 27 | fx.Client.VolumeClient.EXPECT(). 28 | Detach(gomock.Any(), v). 29 | Return(&hcloud.Action{ID: 321}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 321}). 32 | Return(nil) 33 | 34 | out, errOut, err := fx.Run(cmd, []string{"123"}) 35 | 36 | expOut := "Volume 123 detached\n" 37 | 38 | require.NoError(t, err) 39 | assert.Empty(t, errOut) 40 | assert.Equal(t, expOut, out) 41 | } 42 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_all.md: -------------------------------------------------------------------------------- 1 | ## hcloud all 2 | 3 | Commands that apply to all resources 4 | 5 | ### Options 6 | 7 | ``` 8 | -h, --help help for all 9 | ``` 10 | 11 | ### Options inherited from parent commands 12 | 13 | ``` 14 | --config string Config file path (default "~/.config/hcloud/cli.toml") 15 | --context string Currently active context 16 | --debug Enable debug output 17 | --debug-file string File to write debug output to 18 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 19 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 20 | --no-experimental-warnings If true, experimental warnings are not shown 21 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 22 | --quiet If true, only print error messages 23 | ``` 24 | 25 | ### SEE ALSO 26 | 27 | * [hcloud](hcloud.md) - Hetzner Cloud CLI 28 | * [hcloud all list](hcloud_all_list.md) - List all resources in the project 29 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_context_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud context delete 2 | 3 | Delete a context 4 | 5 | ``` 6 | hcloud context delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud context](hcloud_context.md) - Manage contexts 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_network_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud network delete 2 | 3 | Delete a network 4 | 5 | ``` 6 | hcloud network delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud network](hcloud_network.md) - Manage Networks 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_poweroff.md: -------------------------------------------------------------------------------- 1 | ## hcloud server poweroff 2 | 3 | Poweroff a Server 4 | 5 | ``` 6 | hcloud server poweroff 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for poweroff 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_context_rename.md: -------------------------------------------------------------------------------- 1 | ## hcloud context rename 2 | 3 | Rename a context 4 | 5 | ``` 6 | hcloud context rename 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for rename 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud context](hcloud_context.md) - Manage contexts 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_ssh-key_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud ssh-key delete 2 | 3 | Delete an SSH Key 4 | 5 | ``` 6 | hcloud ssh-key delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud ssh-key](hcloud_ssh-key.md) - Manage SSH Keys 32 | -------------------------------------------------------------------------------- /internal/cmd/loadbalancer/delete_service_test.go: -------------------------------------------------------------------------------- 1 | package loadbalancer_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/loadbalancer" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDeleteService(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := loadbalancer.DeleteServiceCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.LoadBalancerClient.EXPECT(). 23 | Get(gomock.Any(), "123"). 24 | Return(&hcloud.LoadBalancer{ID: 123}, nil, nil) 25 | fx.Client.LoadBalancerClient.EXPECT(). 26 | DeleteService(gomock.Any(), &hcloud.LoadBalancer{ID: 123}, 80). 27 | Return(&hcloud.Action{ID: 123}, nil, nil) 28 | 29 | out, errOut, err := fx.Run(cmd, []string{"123", "--listen-port", "80"}) 30 | 31 | expOut := "Service on port 80 deleted from Load Balancer 123\n" 32 | 33 | require.NoError(t, err) 34 | assert.Empty(t, errOut) 35 | assert.Equal(t, expOut, out) 36 | } 37 | -------------------------------------------------------------------------------- /test/e2e/server_test.go: -------------------------------------------------------------------------------- 1 | //go:build e2e 2 | 3 | package e2e 4 | 5 | import ( 6 | "context" 7 | "fmt" 8 | "strconv" 9 | "strings" 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | 14 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 15 | ) 16 | 17 | func createServer(t *testing.T, name, serverType, image string, args ...string) (int64, error) { 18 | t.Helper() 19 | t.Cleanup(func() { 20 | _, _, _ = client.Server.DeleteWithResult(context.Background(), &hcloud.Server{Name: name}) 21 | }) 22 | 23 | out, err := runCommand(t, append([]string{"server", "create", "--name", name, "--type", serverType, "--image", image}, args...)...) 24 | if err != nil { 25 | return 0, err 26 | } 27 | 28 | firstLine := strings.Split(out, "\n")[0] 29 | if !assert.Regexp(t, `^Server [0-9]+ created$`, firstLine) { 30 | return 0, fmt.Errorf("invalid response: %s", out) 31 | } 32 | 33 | id, err := strconv.ParseInt(out[7:len(firstLine)-8], 10, 64) 34 | if err != nil { 35 | return 0, err 36 | } 37 | 38 | t.Cleanup(func() { 39 | _, _, _ = client.Server.DeleteWithResult(context.Background(), &hcloud.Server{ID: int64(id)}) 40 | }) 41 | return id, nil 42 | } 43 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_firewall_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud firewall delete 2 | 3 | Delete a Firewall 4 | 5 | ``` 6 | hcloud firewall delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud firewall](hcloud_firewall.md) - Manage Firewalls 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_zone_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud zone delete 2 | 3 | Delete a Zone 4 | 5 | ``` 6 | hcloud zone delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud zone](hcloud_zone.md) - Manage DNS Zones and Zone RRSets (records) 32 | -------------------------------------------------------------------------------- /internal/cmd/server/reset_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestReset(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.ResetCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | Reset(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Server 123 reset\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_iso.md: -------------------------------------------------------------------------------- 1 | ## hcloud iso 2 | 3 | View ISOs 4 | 5 | ### Options 6 | 7 | ``` 8 | -h, --help help for iso 9 | ``` 10 | 11 | ### Options inherited from parent commands 12 | 13 | ``` 14 | --config string Config file path (default "~/.config/hcloud/cli.toml") 15 | --context string Currently active context 16 | --debug Enable debug output 17 | --debug-file string File to write debug output to 18 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 19 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 20 | --no-experimental-warnings If true, experimental warnings are not shown 21 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 22 | --quiet If true, only print error messages 23 | ``` 24 | 25 | ### SEE ALSO 26 | 27 | * [hcloud](hcloud.md) - Hetzner Cloud CLI 28 | * [hcloud iso describe](hcloud_iso_describe.md) - Describe an ISO 29 | * [hcloud iso list](hcloud_iso_list.md) - List ISOs 30 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_detach-iso.md: -------------------------------------------------------------------------------- 1 | ## hcloud server detach-iso 2 | 3 | Detach an ISO from a Server 4 | 5 | ``` 6 | hcloud server detach-iso 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for detach-iso 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /internal/cmd/iso/describe_test.go: -------------------------------------------------------------------------------- 1 | package iso_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/iso" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDescribe(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := iso.DescribeCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.ISOClient.EXPECT(). 23 | Get(gomock.Any(), "test"). 24 | Return(&hcloud.ISO{ 25 | ID: 123, 26 | Name: "test", 27 | Description: "Test ISO", 28 | Type: hcloud.ISOTypePublic, 29 | Architecture: hcloud.Ptr(hcloud.ArchitectureX86), 30 | }, nil, nil) 31 | 32 | out, errOut, err := fx.Run(cmd, []string{"test"}) 33 | 34 | expOut := `ID: 123 35 | Name: test 36 | Description: Test ISO 37 | Type: public 38 | Architecture: x86 39 | ` 40 | 41 | require.NoError(t, err) 42 | assert.Empty(t, errOut) 43 | assert.Equal(t, expOut, out) 44 | } 45 | -------------------------------------------------------------------------------- /internal/cmd/server/reboot_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestReboot(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.RebootCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | Reboot(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Server 123 rebooted\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_primary-ip_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud primary-ip delete 2 | 3 | Delete a Primary IP 4 | 5 | ``` 6 | hcloud primary-ip delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud primary-ip](hcloud_primary-ip.md) - Manage Primary IPs 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_attach-iso.md: -------------------------------------------------------------------------------- 1 | ## hcloud server attach-iso 2 | 3 | Attach an ISO to a server 4 | 5 | ``` 6 | hcloud server attach-iso 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for attach-iso 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /internal/cmd/server/poweron_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestPoweron(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.PoweronCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | Poweron(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Server 123 started\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/server/update.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "github.com/spf13/pflag" 6 | 7 | "github.com/hetznercloud/cli/internal/cmd/base" 8 | "github.com/hetznercloud/cli/internal/hcapi2" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 11 | ) 12 | 13 | var UpdateCmd = base.UpdateCmd[*hcloud.Server]{ 14 | ResourceNameSingular: "Server", 15 | ShortDescription: "Update a Server", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Server().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Server, *hcloud.Response, error) { 18 | return s.Client().Server().Get(s, idOrName) 19 | }, 20 | DefineFlags: func(cmd *cobra.Command) { 21 | cmd.Flags().String("name", "", "Server name") 22 | }, 23 | Update: func(s state.State, _ *cobra.Command, server *hcloud.Server, flags map[string]pflag.Value) error { 24 | updOpts := hcloud.ServerUpdateOpts{ 25 | Name: flags["name"].String(), 26 | } 27 | _, _, err := s.Client().Server().Update(s, server, updOpts) 28 | if err != nil { 29 | return err 30 | } 31 | return nil 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /internal/cmd/volume/update.go: -------------------------------------------------------------------------------- 1 | package volume 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "github.com/spf13/pflag" 6 | 7 | "github.com/hetznercloud/cli/internal/cmd/base" 8 | "github.com/hetznercloud/cli/internal/hcapi2" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 11 | ) 12 | 13 | var UpdateCmd = base.UpdateCmd[*hcloud.Volume]{ 14 | ResourceNameSingular: "Volume", 15 | ShortDescription: "Update a Volume", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Volume().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Volume, *hcloud.Response, error) { 18 | return s.Client().Volume().Get(s, idOrName) 19 | }, 20 | DefineFlags: func(cmd *cobra.Command) { 21 | cmd.Flags().String("name", "", "Volume name") 22 | }, 23 | Update: func(s state.State, _ *cobra.Command, volume *hcloud.Volume, flags map[string]pflag.Value) error { 24 | updOpts := hcloud.VolumeUpdateOpts{ 25 | Name: flags["name"].String(), 26 | } 27 | _, _, err := s.Client().Volume().Update(s, volume, updOpts) 28 | if err != nil { 29 | return err 30 | } 31 | return nil 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /internal/cmd/server/poweroff_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestPoweroff(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.PoweroffCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | Poweroff(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Server 123 stopped\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/sshkey/update.go: -------------------------------------------------------------------------------- 1 | package sshkey 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "github.com/spf13/pflag" 6 | 7 | "github.com/hetznercloud/cli/internal/cmd/base" 8 | "github.com/hetznercloud/cli/internal/hcapi2" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 11 | ) 12 | 13 | var UpdateCmd = base.UpdateCmd[*hcloud.SSHKey]{ 14 | ResourceNameSingular: "SSH Key", 15 | ShortDescription: "Update an SSH Key", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.SSHKey().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.SSHKey, *hcloud.Response, error) { 18 | return s.Client().SSHKey().Get(s, idOrName) 19 | }, 20 | DefineFlags: func(cmd *cobra.Command) { 21 | cmd.Flags().String("name", "", "SSH Key name") 22 | }, 23 | Update: func(s state.State, _ *cobra.Command, sshKey *hcloud.SSHKey, flags map[string]pflag.Value) error { 24 | updOpts := hcloud.SSHKeyUpdateOpts{ 25 | Name: flags["name"].String(), 26 | } 27 | _, _, err := s.Client().SSHKey().Update(s, sshKey, updOpts) 28 | if err != nil { 29 | return err 30 | } 31 | return nil 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_certificate_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud certificate delete 2 | 3 | Delete a Certificate 4 | 5 | ``` 6 | hcloud certificate delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud certificate](hcloud_certificate.md) - Manage Certificates 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_floating-ip_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud floating-ip delete 2 | 3 | Delete a Floating IP 4 | 5 | ``` 6 | hcloud floating-ip delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud floating-ip](hcloud_floating-ip.md) - Manage Floating IPs 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_disable-backup.md: -------------------------------------------------------------------------------- 1 | ## hcloud server disable-backup 2 | 3 | Disable backup for a server 4 | 5 | ``` 6 | hcloud server disable-backup 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for disable-backup 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_disable-rescue.md: -------------------------------------------------------------------------------- 1 | ## hcloud server disable-rescue 2 | 3 | Disable rescue for a server 4 | 5 | ``` 6 | hcloud server disable-rescue 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for disable-rescue 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud server](hcloud_server.md) - Manage Servers 32 | -------------------------------------------------------------------------------- /internal/cmd/firewall/firewall.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "firewall", 13 | Aliases: []string{"firewalls"}, 14 | Short: "Manage Firewalls", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | 20 | util.AddGroup(cmd, "general", "General", 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | CreateCmd.CobraCommand(s), 24 | DeleteCmd.CobraCommand(s), 25 | UpdateCmd.CobraCommand(s), 26 | LabelCmds.AddCobraCommand(s), 27 | LabelCmds.RemoveCobraCommand(s), 28 | ) 29 | 30 | util.AddGroup(cmd, "rule", "Rules", 31 | ReplaceRulesCmd.CobraCommand(s), 32 | AddRuleCmd.CobraCommand(s), 33 | DeleteRuleCmd.CobraCommand(s), 34 | ) 35 | 36 | util.AddGroup(cmd, "resource", "Resources", 37 | ApplyToResourceCmd.CobraCommand(s), 38 | RemoveFromResourceCmd.CobraCommand(s), 39 | ) 40 | return cmd 41 | } 42 | -------------------------------------------------------------------------------- /internal/cmd/storagebox/texts.go: -------------------------------------------------------------------------------- 1 | package storagebox 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 8 | ) 9 | 10 | func warningDeprecatedStorageBoxType(storageBoxType *hcloud.StorageBoxType) string { 11 | if !storageBoxType.IsDeprecated() { 12 | return "" 13 | } 14 | 15 | if time.Now().After(storageBoxType.UnavailableAfter()) { 16 | return fmt.Sprintf("Attention: The Storage Box Type %q is deprecated and can no longer be ordered. Existing Storage Boxes of that plan will continue to work as before and no action is required on your part. It is possible to migrate this Storage Box to another Storage Box Type by using the \"hcloud storage-box change-type\" command.\n\n", storageBoxType.Name) 17 | } 18 | 19 | return fmt.Sprintf("Attention: The Storage Box Type %q is deprecated and will no longer be available for order as of %s. Existing Storage Boxes of that plan will continue to work as before and no action is required on your part. It is possible to migrate this Storage Box to another Storage Box Type by using the \"hcloud storage-box change-type\" command.\n\n", storageBoxType.Name, storageBoxType.UnavailableAfter().Format(time.DateOnly)) 20 | } 21 | -------------------------------------------------------------------------------- /internal/cmd/volume/volume.go: -------------------------------------------------------------------------------- 1 | package volume 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "volume", 13 | Aliases: []string{"volumes"}, 14 | Short: "Manage Volumes", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | 20 | util.AddGroup(cmd, "general", "General", 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | DeleteCmd.CobraCommand(s), 24 | CreateCmd.CobraCommand(s), 25 | UpdateCmd.CobraCommand(s), 26 | LabelCmds.AddCobraCommand(s), 27 | LabelCmds.RemoveCobraCommand(s), 28 | ResizeCmd.CobraCommand(s), 29 | ) 30 | 31 | util.AddGroup(cmd, "protection", "Protection", 32 | ChangeProtectionCmds.EnableCobraCommand(s), 33 | ChangeProtectionCmds.DisableCobraCommand(s), 34 | ) 35 | 36 | util.AddGroup(cmd, "attach", "Attach", 37 | AttachCmd.CobraCommand(s), 38 | DetachCmd.CobraCommand(s), 39 | ) 40 | return cmd 41 | } 42 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_floating-ip_unassign.md: -------------------------------------------------------------------------------- 1 | ## hcloud floating-ip unassign 2 | 3 | Unassign a Floating IP 4 | 5 | ``` 6 | hcloud floating-ip unassign 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for unassign 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud floating-ip](hcloud_floating-ip.md) - Manage Floating IPs 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_zone_rrset_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud zone rrset delete 2 | 3 | Delete a Zone RRSet 4 | 5 | ``` 6 | hcloud zone rrset delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud zone rrset](hcloud_zone_rrset.md) - Manage Zone RRSets (records) 32 | -------------------------------------------------------------------------------- /internal/ui/progress_test.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestProgressGroup(t *testing.T) { 11 | buffer := bytes.NewBuffer(nil) 12 | 13 | progressGroup := NewProgressGroup(buffer) 14 | progress1 := progressGroup.Add("progress 1", "") 15 | progress2 := progressGroup.Add("progress 2", "") 16 | progress3 := progressGroup.Add("progress 3", "") 17 | 18 | if err := progressGroup.Start(); err != nil { 19 | t.Fatal(err) 20 | } 21 | 22 | progress1.SetSuccess() 23 | progress3.SetError() 24 | progress2.SetSuccess() 25 | 26 | if err := progressGroup.Stop(); err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | assert.Equal(t, 31 | `progress 1 ... 32 | progress 2 ... 33 | progress 3 ... 34 | progress 1 ... done 35 | progress 3 ... failed 36 | progress 2 ... done 37 | `, 38 | buffer.String()) 39 | } 40 | 41 | func TestProgress(t *testing.T) { 42 | buffer := bytes.NewBuffer(nil) 43 | 44 | progress1 := NewProgress(buffer, "progress 1", "") 45 | progress1.Start() 46 | progress1.SetSuccess() 47 | 48 | assert.Equal(t, 49 | `progress 1 ... 50 | progress 1 ... done 51 | `, 52 | buffer.String()) 53 | } 54 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_certificate_retry.md: -------------------------------------------------------------------------------- 1 | ## hcloud certificate retry 2 | 3 | Retry a managed Certificate's issuance 4 | 5 | ``` 6 | hcloud certificate retry 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for retry 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud certificate](hcloud_certificate.md) - Manage Certificates 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_update.md: -------------------------------------------------------------------------------- 1 | ## hcloud server update 2 | 3 | Update a Server 4 | 5 | ``` 6 | hcloud server update [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for update 13 | --name string Server name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud server](hcloud_server.md) - Manage Servers 33 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_update.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume update 2 | 3 | Update a Volume 4 | 5 | ``` 6 | hcloud volume update [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for update 13 | --name string Volume name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 33 | -------------------------------------------------------------------------------- /internal/cmd/server/detach_iso_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDetachISO(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.DetachISOCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | DetachISO(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "ISO detached from Server 123\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_floating-ip_assign.md: -------------------------------------------------------------------------------- 1 | ## hcloud floating-ip assign 2 | 3 | Assign a Floating IP to a server 4 | 5 | ``` 6 | hcloud floating-ip assign 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for assign 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud floating-ip](hcloud_floating-ip.md) - Manage Floating IPs 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_load-balancer_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud load-balancer delete 2 | 3 | Delete a Load Balancer 4 | 5 | ``` 6 | hcloud load-balancer delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud load-balancer](hcloud_load-balancer.md) - Manage Load Balancers 32 | -------------------------------------------------------------------------------- /internal/cmd/floatingip/unassign_test.go: -------------------------------------------------------------------------------- 1 | package floatingip_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/floatingip" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestUnassign(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := floatingip.UnassignCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | fx.Client.FloatingIPClient.EXPECT(). 23 | Get(gomock.Any(), "my-ip"). 24 | Return(&hcloud.FloatingIP{ID: 123}, nil, nil) 25 | fx.Client.FloatingIPClient.EXPECT(). 26 | Unassign(gomock.Any(), &hcloud.FloatingIP{ID: 123}). 27 | Return(&hcloud.Action{ID: 123}, nil, nil) 28 | fx.ActionWaiter.EXPECT(). 29 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 123}). 30 | Return(nil) 31 | 32 | out, errOut, err := fx.Run(cmd, []string{"my-ip"}) 33 | 34 | expOut := "Floating IP 123 unassigned\n" 35 | 36 | require.NoError(t, err) 37 | assert.Empty(t, errOut) 38 | assert.Equal(t, expOut, out) 39 | } 40 | -------------------------------------------------------------------------------- /internal/cmd/server/remove_from_placement_group_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestRemoveFromPlacementGroup(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.RemoveFromPlacementGroupCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := hcloud.Server{ 23 | ID: 42, 24 | Name: "my server", 25 | } 26 | 27 | fx.Client.ServerClient.EXPECT(). 28 | Get(gomock.Any(), srv.Name). 29 | Return(&srv, nil, nil) 30 | fx.Client.ServerClient.EXPECT(). 31 | RemoveFromPlacementGroup(gomock.Any(), &srv) 32 | fx.ActionWaiter.EXPECT().WaitForActions(gomock.Any(), gomock.Any(), nil) 33 | 34 | out, errOut, err := fx.Run(cmd, []string{srv.Name}) 35 | 36 | expOut := `Server 42 removed from Placement Group 37 | ` 38 | 39 | require.NoError(t, err) 40 | assert.Empty(t, errOut) 41 | assert.Equal(t, expOut, out) 42 | } 43 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_ssh-key_update.md: -------------------------------------------------------------------------------- 1 | ## hcloud ssh-key update 2 | 3 | Update an SSH Key 4 | 5 | ``` 6 | hcloud ssh-key update [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for update 13 | --name string SSH Key name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud ssh-key](hcloud_ssh-key.md) - Manage SSH Keys 33 | -------------------------------------------------------------------------------- /internal/cmd/firewall/update.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "github.com/spf13/pflag" 6 | 7 | "github.com/hetznercloud/cli/internal/cmd/base" 8 | "github.com/hetznercloud/cli/internal/hcapi2" 9 | "github.com/hetznercloud/cli/internal/state" 10 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 11 | ) 12 | 13 | var UpdateCmd = base.UpdateCmd[*hcloud.Firewall]{ 14 | ResourceNameSingular: "Firewall", 15 | ShortDescription: "Update a Firewall", 16 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names }, 17 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Firewall, *hcloud.Response, error) { 18 | return s.Client().Firewall().Get(s, idOrName) 19 | }, 20 | DefineFlags: func(cmd *cobra.Command) { 21 | cmd.Flags().String("name", "", "Firewall name") 22 | }, 23 | Update: func(s state.State, _ *cobra.Command, firewall *hcloud.Firewall, flags map[string]pflag.Value) error { 24 | updOpts := hcloud.FirewallUpdateOpts{ 25 | Name: flags["name"].String(), 26 | } 27 | _, _, err := s.Client().Firewall().Update(s, firewall, updOpts) 28 | if err != nil { 29 | return err 30 | } 31 | return nil 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /internal/cmd/server/ssh_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "net" 5 | "testing" 6 | 7 | "go.uber.org/mock/gomock" 8 | 9 | "github.com/hetznercloud/cli/internal/cmd/server" 10 | "github.com/hetznercloud/cli/internal/testutil" 11 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 12 | ) 13 | 14 | func TestSSH(t *testing.T) { 15 | srv := hcloud.Server{ 16 | ID: 42, 17 | Name: "server1", 18 | Status: hcloud.ServerStatusRunning, 19 | PublicNet: hcloud.ServerPublicNet{ 20 | IPv4: hcloud.ServerPublicNetIPv4{ 21 | IP: net.ParseIP("192.168.0.2"), 22 | }, 23 | }, 24 | } 25 | 26 | preRun := func(_ *testing.T, fx *testutil.Fixture) { 27 | fx.Client.ServerClient.EXPECT(). 28 | Get(gomock.Any(), srv.Name). 29 | Return(&srv, nil, nil) 30 | 31 | server.SSHPath = "echo" 32 | } 33 | 34 | testutil.TestCommand(t, &server.SSHCmd, map[string]testutil.TestCase{ 35 | "single arg": { 36 | Args: []string{"ssh", srv.Name}, 37 | PreRun: preRun, 38 | ExpOut: "-l root -p 22 192.168.0.2\n", 39 | }, 40 | "many args": { 41 | Args: []string{"ssh", srv.Name, "ls", "-al"}, 42 | PreRun: preRun, 43 | ExpOut: "-l root -p 22 192.168.0.2 ls -al\n", 44 | }, 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_image_enable-protection.md: -------------------------------------------------------------------------------- 1 | ## hcloud image enable-protection 2 | 3 | Enable resource protection for an Image 4 | 5 | ``` 6 | hcloud image enable-protection delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for enable-protection 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud image](hcloud_image.md) - Manage Images 32 | -------------------------------------------------------------------------------- /internal/cmd/server/disable_backup_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDisableBackup(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.DisableBackupCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | DisableBackup(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Backup disabled for Server 123\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/server/disable_rescue_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestDisableRescue(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.DisableRescueCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | DisableRescue(gomock.Any(), srv). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Rescue disabled for Server 123\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/server/enable_backup_test.go: -------------------------------------------------------------------------------- 1 | package server_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | "go.uber.org/mock/gomock" 9 | 10 | "github.com/hetznercloud/cli/internal/cmd/server" 11 | "github.com/hetznercloud/cli/internal/testutil" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | func TestEnableBackup(t *testing.T) { 16 | fx := testutil.NewFixture(t) 17 | defer fx.Finish() 18 | 19 | cmd := server.EnableBackupCmd.CobraCommand(fx.State()) 20 | fx.ExpectEnsureToken() 21 | 22 | srv := &hcloud.Server{ID: 123, Name: "my-server"} 23 | 24 | fx.Client.ServerClient.EXPECT(). 25 | Get(gomock.Any(), "my-server"). 26 | Return(srv, nil, nil) 27 | fx.Client.ServerClient.EXPECT(). 28 | EnableBackup(gomock.Any(), srv, ""). 29 | Return(&hcloud.Action{ID: 789}, nil, nil) 30 | fx.ActionWaiter.EXPECT(). 31 | WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 789}). 32 | Return(nil) 33 | 34 | args := []string{"my-server"} 35 | out, errOut, err := fx.Run(cmd, args) 36 | 37 | require.NoError(t, err) 38 | assert.Empty(t, errOut) 39 | assert.Equal(t, "Backup enabled for Server 123\n", out) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/zone/delete.go: -------------------------------------------------------------------------------- 1 | package zone 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/hetznercloud/cli/internal/cmd/base" 9 | "github.com/hetznercloud/cli/internal/cmd/util" 10 | "github.com/hetznercloud/cli/internal/hcapi2" 11 | "github.com/hetznercloud/cli/internal/state" 12 | "github.com/hetznercloud/hcloud-go/v2/hcloud" 13 | ) 14 | 15 | var DeleteCmd = base.DeleteCmd[*hcloud.Zone]{ 16 | ResourceNameSingular: "Zone", 17 | ResourceNamePlural: "Zones", 18 | ShortDescription: "Delete a Zone", 19 | NameSuggestions: func(c hcapi2.Client) func() []string { return c.Zone().Names }, 20 | Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Zone, *hcloud.Response, error) { 21 | idOrName, err := util.ParseZoneIDOrName(idOrName) 22 | if err != nil { 23 | return nil, nil, fmt.Errorf("failed to convert Zone name to ascii: %w", err) 24 | } 25 | 26 | return s.Client().Zone().Get(s, idOrName) 27 | }, 28 | Delete: func(s state.State, _ *cobra.Command, zone *hcloud.Zone) (*hcloud.Action, error) { 29 | res, _, err := s.Client().Zone().Delete(s, zone) 30 | if err != nil { 31 | return nil, err 32 | } 33 | return res.Action, nil 34 | }, 35 | } 36 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_firewall_update.md: -------------------------------------------------------------------------------- 1 | ## hcloud firewall update 2 | 3 | Update a Firewall 4 | 5 | ``` 6 | hcloud firewall update [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for update 13 | --name string Firewall name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud firewall](hcloud_firewall.md) - Manage Firewalls 33 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_image_disable-protection.md: -------------------------------------------------------------------------------- 1 | ## hcloud image disable-protection 2 | 3 | Disable resource protection for an Image 4 | 5 | ``` 6 | hcloud image disable-protection delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for disable-protection 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud image](hcloud_image.md) - Manage Images 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_iso_describe.md: -------------------------------------------------------------------------------- 1 | ## hcloud iso describe 2 | 3 | Describe an ISO 4 | 5 | ``` 6 | hcloud iso describe [options] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for describe 13 | -o, --output stringArray output options: json|yaml|format 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud iso](hcloud_iso.md) - View ISOs 33 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_placement-group_delete.md: -------------------------------------------------------------------------------- 1 | ## hcloud placement-group delete 2 | 3 | Delete a Placement Group 4 | 5 | ``` 6 | hcloud placement-group delete ... 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud placement-group](hcloud_placement-group.md) - Manage Placement Groups 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_enable-protection.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume enable-protection 2 | 3 | Enable resource protection for a Volume 4 | 5 | ``` 6 | hcloud volume enable-protection delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for enable-protection 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_location.md: -------------------------------------------------------------------------------- 1 | ## hcloud location 2 | 3 | View Locations 4 | 5 | ### Options 6 | 7 | ``` 8 | -h, --help help for location 9 | ``` 10 | 11 | ### Options inherited from parent commands 12 | 13 | ``` 14 | --config string Config file path (default "~/.config/hcloud/cli.toml") 15 | --context string Currently active context 16 | --debug Enable debug output 17 | --debug-file string File to write debug output to 18 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 19 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 20 | --no-experimental-warnings If true, experimental warnings are not shown 21 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 22 | --quiet If true, only print error messages 23 | ``` 24 | 25 | ### SEE ALSO 26 | 27 | * [hcloud](hcloud.md) - Hetzner Cloud CLI 28 | * [hcloud location describe](hcloud_location_describe.md) - Describe a Location 29 | * [hcloud location list](hcloud_location_list.md) - List Locations 30 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_primary-ip_unassign.md: -------------------------------------------------------------------------------- 1 | ## hcloud primary-ip unassign 2 | 3 | Unassign a Primary IP from an assignee (usually a server) 4 | 5 | ``` 6 | hcloud primary-ip unassign 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for unassign 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud primary-ip](hcloud_primary-ip.md) - Manage Primary IPs 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_disable-protection.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume disable-protection 2 | 3 | Disable resource protection for a Volume 4 | 5 | ``` 6 | hcloud volume disable-protection delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for disable-protection 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_volume_resize.md: -------------------------------------------------------------------------------- 1 | ## hcloud volume resize 2 | 3 | Resize a volume 4 | 5 | ``` 6 | hcloud volume resize --size 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for resize 13 | --size int New size (GB) of the Volume (required) 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud volume](hcloud_volume.md) - Manage Volumes 33 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_network_enable-protection.md: -------------------------------------------------------------------------------- 1 | ## hcloud network enable-protection 2 | 3 | Enable resource protection for a Network 4 | 5 | ``` 6 | hcloud network enable-protection delete 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for enable-protection 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | --config string Config file path (default "~/.config/hcloud/cli.toml") 19 | --context string Currently active context 20 | --debug Enable debug output 21 | --debug-file string File to write debug output to 22 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 23 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 24 | --no-experimental-warnings If true, experimental warnings are not shown 25 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 26 | --quiet If true, only print error messages 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [hcloud network](hcloud_network.md) - Manage Networks 32 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_server_ip.md: -------------------------------------------------------------------------------- 1 | ## hcloud server ip 2 | 3 | Print a server's IP address 4 | 5 | ``` 6 | hcloud server ip [--ipv6] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for ip 13 | -6, --ipv6 Print the first address of the Server's Primary IPv6 network 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | --config string Config file path (default "~/.config/hcloud/cli.toml") 20 | --context string Currently active context 21 | --debug Enable debug output 22 | --debug-file string File to write debug output to 23 | --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") 24 | --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") 25 | --no-experimental-warnings If true, experimental warnings are not shown 26 | --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) 27 | --quiet If true, only print error messages 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [hcloud server](hcloud_server.md) - Manage Servers 33 | -------------------------------------------------------------------------------- /internal/cmd/primaryip/primaryip.go: -------------------------------------------------------------------------------- 1 | package primaryip 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/hetznercloud/cli/internal/cmd/util" 7 | "github.com/hetznercloud/cli/internal/state" 8 | ) 9 | 10 | func NewCommand(s state.State) *cobra.Command { 11 | cmd := &cobra.Command{ 12 | Use: "primary-ip", 13 | Aliases: []string{"primary-ips"}, 14 | Short: "Manage Primary IPs", 15 | Args: util.Validate, 16 | TraverseChildren: true, 17 | DisableFlagsInUseLine: true, 18 | } 19 | 20 | util.AddGroup(cmd, "general", "General", 21 | ListCmd.CobraCommand(s), 22 | DescribeCmd.CobraCommand(s), 23 | DeleteCmd.CobraCommand(s), 24 | CreateCmd.CobraCommand(s), 25 | UpdateCmd.CobraCommand(s), 26 | LabelCmds.AddCobraCommand(s), 27 | LabelCmds.RemoveCobraCommand(s), 28 | ) 29 | 30 | util.AddGroup(cmd, "protection", "Protection", 31 | ChangeProtectionCmds.EnableCobraCommand(s), 32 | ChangeProtectionCmds.DisableCobraCommand(s), 33 | ) 34 | 35 | util.AddGroup(cmd, "assign", "Assign", 36 | AssignCmd.CobraCommand(s), 37 | UnAssignCmd.CobraCommand(s), 38 | ) 39 | 40 | cmd.AddCommand(SetRDNSCmd.CobraCommand(s)) 41 | return cmd 42 | } 43 | -------------------------------------------------------------------------------- /docs/reference/manual/hcloud_image_remove-label.md: -------------------------------------------------------------------------------- 1 | ## hcloud image remove-label 2 | 3 | Remove a label from an Image 4 | 5 | ``` 6 | hcloud image remove-label (--all |