From cf65904a501f32888fe22b721118480b9e9b5c1b Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:26:21 +0200 Subject: [PATCH 01/17] update hcloud-go --- go.mod | 2 +- go.sum | 4 +- .../hcapi2/mock/zz_storage_box_client_mock.go | 48 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ce251b11..006f1ac3 100644 --- a/go.mod +++ b/go.mod @@ -66,4 +66,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/hetznercloud/hcloud-go/v2 => github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009065434-20e0a5fb69a3 +replace github.com/hetznercloud/hcloud-go/v2 => github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009103015-9830b68660d8 diff --git a/go.sum b/go.sum index 089abcbc..03457f27 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/guptarohit/asciigraph v0.7.3 h1:p05XDDn7cBTWiBqWb30mrwxd6oU0claAjqeytllnsPY= github.com/guptarohit/asciigraph v0.7.3/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= -github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009065434-20e0a5fb69a3 h1:X+NjlsE/oHJTDINi0iGpqdNMR8KHRWp9Tp7hbh8/Etg= -github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009065434-20e0a5fb69a3/go.mod h1:weuyv9L3A9iFYAxQW0YkPZHAqjBbYoQYTEXAONYyqYo= +github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009103015-9830b68660d8 h1:BFmoEMO7Eust12bRc4Zb/az4Bokd1lUb7PHhno2jFck= +github.com/hetznercloud/hcloud-go/v2 v2.27.1-0.20251009103015-9830b68660d8/go.mod h1:weuyv9L3A9iFYAxQW0YkPZHAqjBbYoQYTEXAONYyqYo= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= diff --git a/internal/hcapi2/mock/zz_storage_box_client_mock.go b/internal/hcapi2/mock/zz_storage_box_client_mock.go index bc13a73a..1f3167ff 100644 --- a/internal/hcapi2/mock/zz_storage_box_client_mock.go +++ b/internal/hcapi2/mock/zz_storage_box_client_mock.go @@ -147,6 +147,22 @@ func (mr *MockStorageBoxClientMockRecorder) ChangeProtection(ctx, storageBox, op return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeProtection", reflect.TypeOf((*MockStorageBoxClient)(nil).ChangeProtection), ctx, storageBox, opts) } +// ChangeSubaccountHomeDirectory mocks base method. +func (m *MockStorageBoxClient) ChangeSubaccountHomeDirectory(ctx context.Context, subaccount *hcloud.StorageBoxSubaccount, opts hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts) (*hcloud.Action, *hcloud.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChangeSubaccountHomeDirectory", ctx, subaccount, opts) + ret0, _ := ret[0].(*hcloud.Action) + ret1, _ := ret[1].(*hcloud.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// ChangeSubaccountHomeDirectory indicates an expected call of ChangeSubaccountHomeDirectory. +func (mr *MockStorageBoxClientMockRecorder) ChangeSubaccountHomeDirectory(ctx, subaccount, opts any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeSubaccountHomeDirectory", reflect.TypeOf((*MockStorageBoxClient)(nil).ChangeSubaccountHomeDirectory), ctx, subaccount, opts) +} + // ChangeType mocks base method. func (m *MockStorageBoxClient) ChangeType(ctx context.Context, storageBox *hcloud.StorageBox, opts hcloud.StorageBoxChangeTypeOpts) (*hcloud.Action, *hcloud.Response, error) { m.ctrl.T.Helper() @@ -403,6 +419,22 @@ func (mr *MockStorageBoxClientMockRecorder) GetSnapshotByName(ctx, storageBox, n return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSnapshotByName", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSnapshotByName), ctx, storageBox, name) } +// GetSubaccount mocks base method. +func (m *MockStorageBoxClient) GetSubaccount(ctx context.Context, storageBox *hcloud.StorageBox, idOrUsername string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubaccount", ctx, storageBox, idOrUsername) + ret0, _ := ret[0].(*hcloud.StorageBoxSubaccount) + ret1, _ := ret[1].(*hcloud.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetSubaccount indicates an expected call of GetSubaccount. +func (mr *MockStorageBoxClientMockRecorder) GetSubaccount(ctx, storageBox, idOrUsername any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccount", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccount), ctx, storageBox, idOrUsername) +} + // GetSubaccountByID mocks base method. func (m *MockStorageBoxClient) GetSubaccountByID(ctx context.Context, storageBox *hcloud.StorageBox, id int64) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { m.ctrl.T.Helper() @@ -419,6 +451,22 @@ func (mr *MockStorageBoxClientMockRecorder) GetSubaccountByID(ctx, storageBox, i return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccountByID", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccountByID), ctx, storageBox, id) } +// GetSubaccountByUsername mocks base method. +func (m *MockStorageBoxClient) GetSubaccountByUsername(ctx context.Context, storageBox *hcloud.StorageBox, username string) (*hcloud.StorageBoxSubaccount, *hcloud.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubaccountByUsername", ctx, storageBox, username) + ret0, _ := ret[0].(*hcloud.StorageBoxSubaccount) + ret1, _ := ret[1].(*hcloud.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetSubaccountByUsername indicates an expected call of GetSubaccountByUsername. +func (mr *MockStorageBoxClientMockRecorder) GetSubaccountByUsername(ctx, storageBox, username any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubaccountByUsername", reflect.TypeOf((*MockStorageBoxClient)(nil).GetSubaccountByUsername), ctx, storageBox, username) +} + // LabelKeys mocks base method. func (m *MockStorageBoxClient) LabelKeys(arg0 string) []string { m.ctrl.T.Helper() From 24cf63dc9c29cf54c41881c8742273c09e355539 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:26:31 +0200 Subject: [PATCH 02/17] allow sorting in list --- internal/cmd/storagebox/list.go | 13 ++++++++++--- internal/state/config/options.go | 9 +++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/internal/cmd/storagebox/list.go b/internal/cmd/storagebox/list.go index 41e2236f..27e4a673 100644 --- a/internal/cmd/storagebox/list.go +++ b/internal/cmd/storagebox/list.go @@ -11,6 +11,7 @@ import ( "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/state/config" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) @@ -19,10 +20,16 @@ var ListCmd = base.ListCmd[*hcloud.StorageBox, schema.StorageBox]{ ResourceNamePlural: "Storage Boxes", JSONKeyGetByName: "storage_boxes", DefaultColumns: []string{"id", "name", "username", "server", "type", "size", "location", "age"}, - Fetch: func(s state.State, _ *pflag.FlagSet, opts hcloud.ListOpts, _ []string) ([]*hcloud.StorageBox, error) { - listOpts := hcloud.StorageBoxListOpts{ListOpts: opts} - return s.Client().StorageBox().AllWithOpts(s, listOpts) + SortOption: config.OptionSortStorageBox, + + Fetch: func(s state.State, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]*hcloud.StorageBox, error) { + opts := hcloud.StorageBoxListOpts{ListOpts: listOpts} + if len(sorts) > 0 { + opts.Sort = sorts + } + return s.Client().StorageBox().AllWithOpts(s, opts) }, + OutputTable: func(t *output.Table, _ hcapi2.Client) { t. AddAllowedFields(hcloud.StorageBox{}). diff --git a/internal/state/config/options.go b/internal/state/config/options.go index a82573c7..f80798cb 100644 --- a/internal/state/config/options.go +++ b/internal/state/config/options.go @@ -286,6 +286,15 @@ var ( nil, ) + OptionSortStorageBox = newOpt( + "sort.storage-box", + "Default sorting for Storage Box resource", + []string{"id:asc"}, + (DefaultPreferenceFlags&^OptionFlagPFlag)|OptionFlagSlice|OptionFlagHidden, + nil, + nil, + ) + OptionSortVolume = newOpt( "sort.volume", "Default sorting for Volume resource", From 9d3ecbda3e92f9006ea24daa1946ffcd8c465748 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:27:40 +0200 Subject: [PATCH 03/17] stats not nullable --- internal/cmd/storagebox/describe.go | 10 +++------- internal/cmd/storagebox/list.go | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/internal/cmd/storagebox/describe.go b/internal/cmd/storagebox/describe.go index cecbdf5f..9c0aad96 100644 --- a/internal/cmd/storagebox/describe.go +++ b/internal/cmd/storagebox/describe.go @@ -59,13 +59,9 @@ var DescribeCmd = base.DescribeCmd[*hcloud.StorageBox]{ stats := storageBox.Stats cmd.Println("Stats:") - if stats == nil { - cmd.Println(" No stats available") - } else { - cmd.Printf(" Size:\t\t\t\t%s\n", humanize.IBytes(stats.Size)) - cmd.Printf(" Size Data:\t\t\t%s\n", humanize.IBytes(stats.SizeData)) - cmd.Printf(" Size Snapshots:\t\t%s\n", humanize.IBytes(stats.SizeSnapshots)) - } + cmd.Printf(" Size:\t\t\t\t%s\n", humanize.IBytes(stats.Size)) + cmd.Printf(" Size Data:\t\t\t%s\n", humanize.IBytes(stats.SizeData)) + cmd.Printf(" Size Snapshots:\t\t%s\n", humanize.IBytes(stats.SizeSnapshots)) cmd.Print("Labels:\n") if len(storageBox.Labels) == 0 { diff --git a/internal/cmd/storagebox/list.go b/internal/cmd/storagebox/list.go index 27e4a673..abc2f7c8 100644 --- a/internal/cmd/storagebox/list.go +++ b/internal/cmd/storagebox/list.go @@ -55,9 +55,6 @@ var ListCmd = base.ListCmd[*hcloud.StorageBox, schema.StorageBox]{ }). AddFieldFn("size", func(obj any) string { storageBox := obj.(*hcloud.StorageBox) - if storageBox.Stats == nil { - return "-" - } return humanize.IBytes(storageBox.Stats.Size) }). AddFieldFn("labels", func(obj any) string { From ba501fea93ad4a6942bfeae9ce4c858b0ded41f7 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:37:16 +0200 Subject: [PATCH 04/17] StorageBoxSubaccountAccessSettingsOpts > StorageBoxSubaccountCreateOptsAccessSettings --- internal/cmd/storagebox/subaccount/create.go | 2 +- internal/cmd/storagebox/subaccount/create_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cmd/storagebox/subaccount/create.go b/internal/cmd/storagebox/subaccount/create.go index 8c5fe38c..47068399 100644 --- a/internal/cmd/storagebox/subaccount/create.go +++ b/internal/cmd/storagebox/subaccount/create.go @@ -65,7 +65,7 @@ var CreateCmd = base.CreateCmd[*hcloud.StorageBoxSubaccount]{ opts := hcloud.StorageBoxSubaccountCreateOpts{ Password: password, HomeDirectory: &homeDirectory, - AccessSettings: &hcloud.StorageBoxSubaccountAccessSettingsOpts{ + AccessSettings: &hcloud.StorageBoxSubaccountCreateOptsAccessSettings{ ReachableExternally: &reachableExternally, SambaEnabled: &enableSamba, SSHEnabled: &enableSSH, diff --git a/internal/cmd/storagebox/subaccount/create_test.go b/internal/cmd/storagebox/subaccount/create_test.go index 37b18b02..b6e67883 100644 --- a/internal/cmd/storagebox/subaccount/create_test.go +++ b/internal/cmd/storagebox/subaccount/create_test.go @@ -40,7 +40,7 @@ func TestCreate(t *testing.T) { CreateSubaccount(gomock.Any(), sb, hcloud.StorageBoxSubaccountCreateOpts{ Password: "my-password", HomeDirectory: hcloud.Ptr("/home/directory"), - AccessSettings: &hcloud.StorageBoxSubaccountAccessSettingsOpts{ + AccessSettings: &hcloud.StorageBoxSubaccountCreateOptsAccessSettings{ ReachableExternally: hcloud.Ptr(false), Readonly: hcloud.Ptr(true), SambaEnabled: hcloud.Ptr(false), @@ -112,7 +112,7 @@ func TestCreateJSON(t *testing.T) { CreateSubaccount(gomock.Any(), sb, hcloud.StorageBoxSubaccountCreateOpts{ Password: "my-password", HomeDirectory: hcloud.Ptr("/home/directory"), - AccessSettings: &hcloud.StorageBoxSubaccountAccessSettingsOpts{ + AccessSettings: &hcloud.StorageBoxSubaccountCreateOptsAccessSettings{ ReachableExternally: hcloud.Ptr(false), Readonly: hcloud.Ptr(true), SambaEnabled: hcloud.Ptr(false), From e85143f842a203b8698feb2b6c83d6309d87520e Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:37:25 +0200 Subject: [PATCH 05/17] allow sorting subaccounts --- internal/cmd/storagebox/subaccount/list.go | 7 ++++++- internal/state/config/options.go | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/internal/cmd/storagebox/subaccount/list.go b/internal/cmd/storagebox/subaccount/list.go index 660360b9..be34b58d 100644 --- a/internal/cmd/storagebox/subaccount/list.go +++ b/internal/cmd/storagebox/subaccount/list.go @@ -13,6 +13,7 @@ import ( "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/state/config" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) @@ -28,8 +29,9 @@ var ListCmd = base.ListCmd[*hcloud.StorageBoxSubaccount, schema.StorageBoxSubacc }, PositionalArgumentOverride: []string{"storage-box"}, + SortOption: config.OptionSortStorageBoxSubaccount, - FetchWithArgs: func(s state.State, _ *pflag.FlagSet, listOpts hcloud.ListOpts, _ []string, args []string) ([]*hcloud.StorageBoxSubaccount, error) { + FetchWithArgs: func(s state.State, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string, args []string) ([]*hcloud.StorageBoxSubaccount, error) { storageBoxIDOrName := args[0] storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) @@ -41,6 +43,9 @@ var ListCmd = base.ListCmd[*hcloud.StorageBoxSubaccount, schema.StorageBoxSubacc } opts := hcloud.StorageBoxSubaccountListOpts{LabelSelector: listOpts.LabelSelector} + if len(sorts) > 0 { + opts.Sort = sorts + } return s.Client().StorageBox().AllSubaccountsWithOpts(s, storageBox, opts) }, diff --git a/internal/state/config/options.go b/internal/state/config/options.go index f80798cb..f582eeae 100644 --- a/internal/state/config/options.go +++ b/internal/state/config/options.go @@ -295,6 +295,15 @@ var ( nil, ) + OptionSortStorageBoxSubaccount = newOpt( + "sort.storage-box.subaccount", + "Default sorting for Storage Box Subaccount resource", + []string{"id:asc"}, + (DefaultPreferenceFlags&^OptionFlagPFlag)|OptionFlagSlice|OptionFlagHidden, + nil, + nil, + ) + OptionSortVolume = newOpt( "sort.volume", "Default sorting for Volume resource", From e697ea557fad45f64cd0aadfffe20e19e94e9cb4 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:48:21 +0200 Subject: [PATCH 06/17] snapshot sort opts + filter by is_automatic --- internal/cmd/storagebox/snapshot/list.go | 15 ++++++++++++++- internal/state/config/options.go | 9 +++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/internal/cmd/storagebox/snapshot/list.go b/internal/cmd/storagebox/snapshot/list.go index 2df9477f..1e2263ae 100644 --- a/internal/cmd/storagebox/snapshot/list.go +++ b/internal/cmd/storagebox/snapshot/list.go @@ -14,6 +14,7 @@ import ( "github.com/hetznercloud/cli/internal/cmd/util" "github.com/hetznercloud/cli/internal/hcapi2" "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/state/config" "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" ) @@ -29,9 +30,15 @@ var ListCmd = base.ListCmd[*hcloud.StorageBoxSnapshot, schema.StorageBoxSnapshot }, PositionalArgumentOverride: []string{"storage-box"}, + SortOption: config.OptionSortStorageBoxSnapshot, - FetchWithArgs: func(s state.State, _ *pflag.FlagSet, listOpts hcloud.ListOpts, _ []string, args []string) ([]*hcloud.StorageBoxSnapshot, error) { + AdditionalFlags: func(cmd *cobra.Command) { + cmd.Flags().Bool("automatic", false, "Only show automatic snapshots (true, false)") + }, + + FetchWithArgs: func(s state.State, flags *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string, args []string) ([]*hcloud.StorageBoxSnapshot, error) { storageBoxIDOrName := args[0] + isAutomatic, _ := flags.GetBool("automatic") storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { @@ -42,6 +49,12 @@ var ListCmd = base.ListCmd[*hcloud.StorageBoxSnapshot, schema.StorageBoxSnapshot } opts := hcloud.StorageBoxSnapshotListOpts{LabelSelector: listOpts.LabelSelector} + if len(sorts) > 0 { + opts.Sort = sorts + } + if flags.Changed("automatic") { + opts.IsAutomatic = &isAutomatic + } return s.Client().StorageBox().AllSnapshotsWithOpts(s, storageBox, opts) }, diff --git a/internal/state/config/options.go b/internal/state/config/options.go index f582eeae..44a2292e 100644 --- a/internal/state/config/options.go +++ b/internal/state/config/options.go @@ -295,6 +295,15 @@ var ( nil, ) + OptionSortStorageBoxSnapshot = newOpt( + "sort.storage-box.snapshot", + "Default sorting for Storage Box Snapshot resource", + []string{"id:asc"}, + (DefaultPreferenceFlags&^OptionFlagPFlag)|OptionFlagSlice|OptionFlagHidden, + nil, + nil, + ) + OptionSortStorageBoxSubaccount = newOpt( "sort.storage-box.subaccount", "Default sorting for Storage Box Subaccount resource", From 647deb2eaa22bc4589e2a6f6744deadb4cf134e5 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 10:49:33 +0200 Subject: [PATCH 07/17] name is optional in StorageBoxUpdateOpts --- internal/cmd/storagebox/update.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/storagebox/update.go b/internal/cmd/storagebox/update.go index e0e885a2..6bf98711 100644 --- a/internal/cmd/storagebox/update.go +++ b/internal/cmd/storagebox/update.go @@ -23,7 +23,7 @@ var UpdateCmd = base.UpdateCmd{ Update: func(s state.State, _ *cobra.Command, resource interface{}, flags map[string]pflag.Value) error { storageBox := resource.(*hcloud.StorageBox) opts := hcloud.StorageBoxUpdateOpts{ - Name: flags["name"].String(), + Name: hcloud.Ptr(flags["name"].String()), } _, _, err := s.Client().StorageBox().Update(s, storageBox, opts) if err != nil { From 66900ae1d6d1015ac3ca63b443aa595ddd1b0970 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:24:59 +0200 Subject: [PATCH 08/17] move changing home-directory to its own action --- .../subaccount/change_home_directory.go | 73 +++++++++++++++++++ .../subaccount/change_home_directory_test.go | 46 ++++++++++++ .../cmd/storagebox/subaccount/subaccount.go | 1 + .../subaccount/update_access_settings.go | 5 -- .../subaccount/update_access_settings_test.go | 1 - 5 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 internal/cmd/storagebox/subaccount/change_home_directory.go create mode 100644 internal/cmd/storagebox/subaccount/change_home_directory_test.go diff --git a/internal/cmd/storagebox/subaccount/change_home_directory.go b/internal/cmd/storagebox/subaccount/change_home_directory.go new file mode 100644 index 00000000..dfbe35ea --- /dev/null +++ b/internal/cmd/storagebox/subaccount/change_home_directory.go @@ -0,0 +1,73 @@ +package subaccount + +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" + + "github.com/hetznercloud/cli/internal/cmd/base" + "github.com/hetznercloud/cli/internal/cmd/cmpl" + "github.com/hetznercloud/cli/internal/hcapi2" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +var ChangeHomeDirectoryCmd = base.Cmd{ + BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { + + cmd := &cobra.Command{ + Use: "change-home-directory --home-directory ", + Short: "Update access settings of the Storage Box Subaccount", + ValidArgsFunction: cmpl.SuggestArgs( + cmpl.SuggestCandidatesF(client.StorageBox().Names), + SuggestSubaccounts(client), + ), + TraverseChildren: true, + DisableFlagsInUseLine: true, + } + + cmd.Flags().String("home-directory", "", "Home directory of the Subaccount. Will be created if it doesn't exist yet") + _ = cmd.MarkFlagRequired("home-directory") + + return cmd + }, + Run: func(s state.State, cmd *cobra.Command, args []string) error { + idOrName := args[0] + homeDirectory, _ := cmd.Flags().GetString("home-directory") + + storageBox, _, err := s.Client().StorageBox().Get(s, idOrName) + if err != nil { + return err + } + if storageBox == nil { + return fmt.Errorf("Storage Box not found: %s", idOrName) + } + + id, err := strconv.ParseInt(args[1], 10, 64) + if err != nil { + return fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) + } + subaccount, _, err := s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + if err != nil { + return err + } + if subaccount == nil { + return fmt.Errorf("Storage Box Subaccount not found: %d", id) + } + + action, _, err := s.Client().StorageBox().ChangeSubaccountHomeDirectory(s, subaccount, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ + HomeDirectory: &homeDirectory, + }) + if err != nil { + return err + } + + if err := s.WaitForActions(s, cmd, action); err != nil { + return err + } + + cmd.Printf("Home directory updated for Storage Box Subaccount %d\n", subaccount.ID) + return nil + }, +} diff --git a/internal/cmd/storagebox/subaccount/change_home_directory_test.go b/internal/cmd/storagebox/subaccount/change_home_directory_test.go new file mode 100644 index 00000000..3f1518ca --- /dev/null +++ b/internal/cmd/storagebox/subaccount/change_home_directory_test.go @@ -0,0 +1,46 @@ +package subaccount_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + + "github.com/hetznercloud/cli/internal/cmd/storagebox/subaccount" + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestChangeHomeDirectory(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := subaccount.ChangeHomeDirectoryCmd.CobraCommand(fx.State()) + fx.ExpectEnsureToken() + + sb := &hcloud.StorageBox{ID: 123, Name: "my-storage-box"} + sbs := &hcloud.StorageBoxSubaccount{ID: 456, StorageBox: sb} + + fx.Client.StorageBoxClient.EXPECT(). + Get(gomock.Any(), "my-storage-box"). + Return(sb, nil, nil) + fx.Client.StorageBoxClient.EXPECT(). + GetSubaccountByID(gomock.Any(), sb, int64(456)). + Return(sbs, nil, nil) + fx.Client.StorageBoxClient.EXPECT(). + ChangeSubaccountHomeDirectory(gomock.Any(), sbs, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ + HomeDirectory: hcloud.Ptr("/new/home"), + }). + Return(&hcloud.Action{ID: 456}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 456}). + Return(nil) + + args := []string{"my-storage-box", "456", "--home-directory", "/new/home"} + out, errOut, err := fx.Run(cmd, args) + + require.NoError(t, err) + assert.Empty(t, errOut) + assert.Equal(t, "Home directory updated for Storage Box Subaccount 456\n", out) +} diff --git a/internal/cmd/storagebox/subaccount/subaccount.go b/internal/cmd/storagebox/subaccount/subaccount.go index d34203f6..90ffb1f9 100644 --- a/internal/cmd/storagebox/subaccount/subaccount.go +++ b/internal/cmd/storagebox/subaccount/subaccount.go @@ -24,6 +24,7 @@ func NewCommand(s state.State) *cobra.Command { DescribeCmd.CobraCommand(s), ResetPasswordCmd.CobraCommand(s), UpdateAccessSettingsCmd.CobraCommand(s), + ChangeHomeDirectoryCmd.CobraCommand(s), ) return cmd } diff --git a/internal/cmd/storagebox/subaccount/update_access_settings.go b/internal/cmd/storagebox/subaccount/update_access_settings.go index d5965f59..5da3ffe8 100644 --- a/internal/cmd/storagebox/subaccount/update_access_settings.go +++ b/internal/cmd/storagebox/subaccount/update_access_settings.go @@ -27,7 +27,6 @@ var UpdateAccessSettingsCmd = base.Cmd{ DisableFlagsInUseLine: true, } - cmd.Flags().String("home-directory", "", "Home directory of the Subaccount. Will be created if it doesn't exist yet") cmd.Flags().Bool("enable-samba", false, "Whether the Samba subsystem should be enabled (true, false)") cmd.Flags().Bool("enable-ssh", false, "Whether the SSH subsystem should be enabled (true, false)") cmd.Flags().Bool("enable-webdav", false, "Whether the WebDAV subsystem should be enabled (true, false)") @@ -40,7 +39,6 @@ var UpdateAccessSettingsCmd = base.Cmd{ }, Run: func(s state.State, cmd *cobra.Command, args []string) error { idOrName := args[0] - homeDirectory, _ := cmd.Flags().GetString("home-directory") enableSamba, _ := cmd.Flags().GetBool("enable-samba") enableSSH, _ := cmd.Flags().GetBool("enable-ssh") enableWebDAV, _ := cmd.Flags().GetBool("enable-webdav") @@ -68,9 +66,6 @@ var UpdateAccessSettingsCmd = base.Cmd{ } var opts hcloud.StorageBoxSubaccountAccessSettingsUpdateOpts - if cmd.Flags().Changed("home-directory") { - opts.HomeDirectory = &homeDirectory - } if cmd.Flags().Changed("enable-samba") { opts.SambaEnabled = &enableSamba } diff --git a/internal/cmd/storagebox/subaccount/update_access_settings_test.go b/internal/cmd/storagebox/subaccount/update_access_settings_test.go index ab096b5b..1f485110 100644 --- a/internal/cmd/storagebox/subaccount/update_access_settings_test.go +++ b/internal/cmd/storagebox/subaccount/update_access_settings_test.go @@ -30,7 +30,6 @@ func TestUpdateAccessSettings(t *testing.T) { Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). UpdateSubaccountAccessSettings(gomock.Any(), sbs, hcloud.StorageBoxSubaccountAccessSettingsUpdateOpts{ - HomeDirectory: hcloud.Ptr("/new/home"), SambaEnabled: nil, SSHEnabled: hcloud.Ptr(true), WebDAVEnabled: hcloud.Ptr(false), From 4d1ea1ac3bb4a763f97f79d0f548be5aa99f2674 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:52:57 +0200 Subject: [PATCH 09/17] use GetSubaccount instead of ...ByID --- .../subaccount/change_home_directory.go | 15 +++++---------- internal/cmd/storagebox/subaccount/cmpl.go | 7 +++---- internal/cmd/storagebox/subaccount/delete.go | 9 ++------- internal/cmd/storagebox/subaccount/describe.go | 10 ++-------- .../cmd/storagebox/subaccount/reset_password.go | 15 +++++---------- internal/cmd/storagebox/subaccount/update.go | 12 ++++-------- .../subaccount/update_access_settings.go | 15 +++++---------- 7 files changed, 26 insertions(+), 57 deletions(-) diff --git a/internal/cmd/storagebox/subaccount/change_home_directory.go b/internal/cmd/storagebox/subaccount/change_home_directory.go index dfbe35ea..743ec96b 100644 --- a/internal/cmd/storagebox/subaccount/change_home_directory.go +++ b/internal/cmd/storagebox/subaccount/change_home_directory.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/spf13/cobra" @@ -33,27 +32,23 @@ var ChangeHomeDirectoryCmd = base.Cmd{ return cmd }, Run: func(s state.State, cmd *cobra.Command, args []string) error { - idOrName := args[0] + storageBoxIDOrName, subaccountIDOrName := args[0], args[1] homeDirectory, _ := cmd.Flags().GetString("home-directory") - storageBox, _, err := s.Client().StorageBox().Get(s, idOrName) + storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { return err } if storageBox == nil { - return fmt.Errorf("Storage Box not found: %s", idOrName) + return fmt.Errorf("Storage Box not found: %s", storageBoxIDOrName) } - id, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) - } - subaccount, _, err := s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + subaccount, _, err := s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) if err != nil { return err } if subaccount == nil { - return fmt.Errorf("Storage Box Subaccount not found: %d", id) + return fmt.Errorf("Storage Box Subaccount not found: %s", subaccountIDOrName) } action, _, err := s.Client().StorageBox().ChangeSubaccountHomeDirectory(s, subaccount, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ diff --git a/internal/cmd/storagebox/subaccount/cmpl.go b/internal/cmd/storagebox/subaccount/cmpl.go index 2f0279b4..96374f55 100644 --- a/internal/cmd/storagebox/subaccount/cmpl.go +++ b/internal/cmd/storagebox/subaccount/cmpl.go @@ -2,7 +2,6 @@ package subaccount import ( "context" - "strconv" "github.com/spf13/cobra" @@ -26,10 +25,10 @@ func SuggestSubaccounts(client hcapi2.Client) cobra.CompletionFunc { return nil } - subaccountIDs := make([]string, 0, len(subaccounts)) + subaccountUsernames := make([]string, 0, len(subaccounts)) for _, subaccount := range subaccounts { - subaccountIDs = append(subaccountIDs, strconv.FormatInt(subaccount.ID, 10)) + subaccountUsernames = append(subaccountUsernames, subaccount.Username) } - return subaccountIDs + return subaccountUsernames }) } diff --git a/internal/cmd/storagebox/subaccount/delete.go b/internal/cmd/storagebox/subaccount/delete.go index a65fb0a7..b5413b61 100644 --- a/internal/cmd/storagebox/subaccount/delete.go +++ b/internal/cmd/storagebox/subaccount/delete.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/spf13/cobra" @@ -33,12 +32,8 @@ var DeleteCmd = base.DeleteCmd{ if storageBox == nil { return nil, fmt.Errorf("Storage Box not found: %s", args[0]) } - return func(s state.State, _ *cobra.Command, idStr string) (any, *hcloud.Response, error) { - id, err := strconv.ParseInt(idStr, 10, 64) - if err != nil { - return nil, nil, fmt.Errorf("invalid Storage Box Subaccount ID: %s", idStr) - } - return s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + return func(s state.State, _ *cobra.Command, idOrName string) (any, *hcloud.Response, error) { + return s.Client().StorageBox().GetSubaccount(s, storageBox, idOrName) }, nil }, diff --git a/internal/cmd/storagebox/subaccount/describe.go b/internal/cmd/storagebox/subaccount/describe.go index fa38372e..cefb1448 100644 --- a/internal/cmd/storagebox/subaccount/describe.go +++ b/internal/cmd/storagebox/subaccount/describe.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/dustin/go-humanize" "github.com/spf13/cobra" @@ -26,7 +25,7 @@ var DescribeCmd = base.DescribeCmd[*hcloud.StorageBoxSubaccount]{ } }, FetchWithArgs: func(s state.State, _ *cobra.Command, args []string) (*hcloud.StorageBoxSubaccount, any, error) { - storageBoxIDOrName := args[0] + storageBoxIDOrName, subaccountIDOrName := args[0], args[1] storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { @@ -36,12 +35,7 @@ var DescribeCmd = base.DescribeCmd[*hcloud.StorageBoxSubaccount]{ return nil, nil, fmt.Errorf("Storage Box not found: %s", storageBoxIDOrName) } - id, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return nil, nil, fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) - } - - subaccount, _, err := s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + subaccount, _, err := s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) if err != nil { return nil, nil, err } diff --git a/internal/cmd/storagebox/subaccount/reset_password.go b/internal/cmd/storagebox/subaccount/reset_password.go index 30472359..1a89173c 100644 --- a/internal/cmd/storagebox/subaccount/reset_password.go +++ b/internal/cmd/storagebox/subaccount/reset_password.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/spf13/cobra" @@ -32,27 +31,23 @@ var ResetPasswordCmd = base.Cmd{ return cmd }, Run: func(s state.State, cmd *cobra.Command, args []string) error { - idOrName := args[0] + storageBoxIDOrName, subaccountIDOrName := args[0], args[1] password, _ := cmd.Flags().GetString("password") - storageBox, _, err := s.Client().StorageBox().Get(s, idOrName) + storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { return err } if storageBox == nil { - return fmt.Errorf("Storage Box not found: %s", idOrName) + return fmt.Errorf("Storage Box not found: %s", storageBoxIDOrName) } - id, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) - } - subaccount, _, err := s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + subaccount, _, err := s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) if err != nil { return err } if subaccount == nil { - return fmt.Errorf("Storage Box Subaccount not found: %d", id) + return fmt.Errorf("Storage Box Subaccount not found: %s", subaccountIDOrName) } opts := hcloud.StorageBoxSubaccountResetPasswordOpts{ diff --git a/internal/cmd/storagebox/subaccount/update.go b/internal/cmd/storagebox/subaccount/update.go index b20ee251..f49ad127 100644 --- a/internal/cmd/storagebox/subaccount/update.go +++ b/internal/cmd/storagebox/subaccount/update.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -26,18 +25,15 @@ var UpdateCmd = base.UpdateCmd{ }, PositionalArgumentOverride: []string{"storage-box", "subaccount"}, FetchWithArgs: func(s state.State, _ *cobra.Command, args []string) (any, *hcloud.Response, error) { - storageBox, _, err := s.Client().StorageBox().Get(s, args[0]) + storageBoxIDOrName, subaccountIDOrName := args[0], args[1] + storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { return nil, nil, err } if storageBox == nil { - return nil, nil, fmt.Errorf("Storage Box not found: %s", args[0]) + return nil, nil, fmt.Errorf("Storage Box not found: %s", storageBoxIDOrName) } - id, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return nil, nil, fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) - } - return s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + return s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) }, DefineFlags: func(cmd *cobra.Command) { cmd.Flags().String("description", "", "Description of the Storage Box Snapshot") diff --git a/internal/cmd/storagebox/subaccount/update_access_settings.go b/internal/cmd/storagebox/subaccount/update_access_settings.go index 5da3ffe8..372dc524 100644 --- a/internal/cmd/storagebox/subaccount/update_access_settings.go +++ b/internal/cmd/storagebox/subaccount/update_access_settings.go @@ -2,7 +2,6 @@ package subaccount import ( "fmt" - "strconv" "github.com/spf13/cobra" @@ -38,31 +37,27 @@ var UpdateAccessSettingsCmd = base.Cmd{ return cmd }, Run: func(s state.State, cmd *cobra.Command, args []string) error { - idOrName := args[0] + storageBoxIDOrName, subaccountIDOrName := args[0], args[1] enableSamba, _ := cmd.Flags().GetBool("enable-samba") enableSSH, _ := cmd.Flags().GetBool("enable-ssh") enableWebDAV, _ := cmd.Flags().GetBool("enable-webdav") reachableExternally, _ := cmd.Flags().GetBool("reachable-externally") readonly, _ := cmd.Flags().GetBool("readonly") - storageBox, _, err := s.Client().StorageBox().Get(s, idOrName) + storageBox, _, err := s.Client().StorageBox().Get(s, storageBoxIDOrName) if err != nil { return err } if storageBox == nil { - return fmt.Errorf("Storage Box not found: %s", idOrName) + return fmt.Errorf("Storage Box not found: %s", storageBoxIDOrName) } - id, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return fmt.Errorf("invalid Storage Box Subaccount ID: %s", args[1]) - } - subaccount, _, err := s.Client().StorageBox().GetSubaccountByID(s, storageBox, id) + subaccount, _, err := s.Client().StorageBox().GetSubaccount(s, storageBox, subaccountIDOrName) if err != nil { return err } if subaccount == nil { - return fmt.Errorf("Storage Box Subaccount not found: %d", id) + return fmt.Errorf("Storage Box Subaccount not found: %s", subaccountIDOrName) } var opts hcloud.StorageBoxSubaccountAccessSettingsUpdateOpts From a2c24b784f963afb2de11868691f280f2cc95b8b Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:28:34 +0200 Subject: [PATCH 10/17] go generate --- .../hcloud_storage-box_snapshot_list.md | 1 + .../manual/hcloud_storage-box_subaccount.md | 1 + ...ge-box_subaccount_change-home-directory.md | 32 +++++++++++++++++++ ...e-box_subaccount_update-access-settings.md | 13 ++++---- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 docs/reference/manual/hcloud_storage-box_subaccount_change-home-directory.md diff --git a/docs/reference/manual/hcloud_storage-box_snapshot_list.md b/docs/reference/manual/hcloud_storage-box_snapshot_list.md index ca0f6cce..8b8bc91c 100644 --- a/docs/reference/manual/hcloud_storage-box_snapshot_list.md +++ b/docs/reference/manual/hcloud_storage-box_snapshot_list.md @@ -28,6 +28,7 @@ hcloud storage-box snapshot list [options] ### Options ``` + --automatic Only show automatic snapshots (true, false) -h, --help help for list -o, --output stringArray output options: noheader|columns=...|json|yaml -l, --selector string Selector to filter by labels diff --git a/docs/reference/manual/hcloud_storage-box_subaccount.md b/docs/reference/manual/hcloud_storage-box_subaccount.md index b59f6bf1..146b1ec3 100644 --- a/docs/reference/manual/hcloud_storage-box_subaccount.md +++ b/docs/reference/manual/hcloud_storage-box_subaccount.md @@ -25,6 +25,7 @@ Manage Storage Box Subaccounts ### SEE ALSO * [hcloud storage-box](hcloud_storage-box.md) - Manage Storage Boxes +* [hcloud storage-box subaccount change-home-directory](hcloud_storage-box_subaccount_change-home-directory.md) - Update access settings of the Storage Box Subaccount * [hcloud storage-box subaccount create](hcloud_storage-box_subaccount_create.md) - Create a Storage Box Subaccount * [hcloud storage-box subaccount delete](hcloud_storage-box_subaccount_delete.md) - Delete a Storage Box Subaccount * [hcloud storage-box subaccount describe](hcloud_storage-box_subaccount_describe.md) - Describe a Storage Box Subaccount diff --git a/docs/reference/manual/hcloud_storage-box_subaccount_change-home-directory.md b/docs/reference/manual/hcloud_storage-box_subaccount_change-home-directory.md new file mode 100644 index 00000000..ec5f660a --- /dev/null +++ b/docs/reference/manual/hcloud_storage-box_subaccount_change-home-directory.md @@ -0,0 +1,32 @@ +## hcloud storage-box subaccount change-home-directory + +Update access settings of the Storage Box Subaccount + +``` +hcloud storage-box subaccount change-home-directory --home-directory +``` + +### Options + +``` + -h, --help help for change-home-directory + --home-directory string Home directory of the Subaccount. Will be created if it doesn't exist yet +``` + +### Options inherited from parent commands + +``` + --config string Config file path (default "~/.config/hcloud/cli.toml") + --context string Currently active context + --debug Enable debug output + --debug-file string File to write debug output to + --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") + --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") + --no-experimental-warnings If true, experimental warnings are not shown + --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) + --quiet If true, only print error messages +``` + +### SEE ALSO + +* [hcloud storage-box subaccount](hcloud_storage-box_subaccount.md) - Manage Storage Box Subaccounts diff --git a/docs/reference/manual/hcloud_storage-box_subaccount_update-access-settings.md b/docs/reference/manual/hcloud_storage-box_subaccount_update-access-settings.md index c1da2b0f..6a7fa272 100644 --- a/docs/reference/manual/hcloud_storage-box_subaccount_update-access-settings.md +++ b/docs/reference/manual/hcloud_storage-box_subaccount_update-access-settings.md @@ -9,13 +9,12 @@ hcloud storage-box subaccount update-access-settings [options] Date: Thu, 9 Oct 2025 14:44:11 +0200 Subject: [PATCH 11/17] fix test --- internal/cmd/storagebox/create_test.go | 2 +- internal/cmd/storagebox/describe_test.go | 2 +- internal/cmd/storagebox/list_test.go | 3 ++- internal/cmd/storagebox/snapshot/list_test.go | 2 +- .../subaccount/change_home_directory_test.go | 2 +- internal/cmd/storagebox/subaccount/delete_test.go | 11 ++++++----- internal/cmd/storagebox/subaccount/describe_test.go | 2 +- internal/cmd/storagebox/subaccount/list_test.go | 2 +- .../cmd/storagebox/subaccount/reset_password_test.go | 2 +- .../subaccount/update_access_settings_test.go | 4 ++-- internal/cmd/storagebox/subaccount/update_test.go | 2 +- internal/cmd/storagebox/update_test.go | 2 +- 12 files changed, 19 insertions(+), 17 deletions(-) diff --git a/internal/cmd/storagebox/create_test.go b/internal/cmd/storagebox/create_test.go index e489e710..538c57d8 100644 --- a/internal/cmd/storagebox/create_test.go +++ b/internal/cmd/storagebox/create_test.go @@ -143,7 +143,7 @@ func TestCreateJSON(t *testing.T) { }, Server: hcloud.Ptr("u1337.your-storagebox.de"), System: hcloud.Ptr("FSN1-BX355"), - Stats: &hcloud.StorageBoxStats{ + Stats: hcloud.StorageBoxStats{ Size: 0, SizeData: 0, SizeSnapshots: 0, diff --git a/internal/cmd/storagebox/describe_test.go b/internal/cmd/storagebox/describe_test.go index 7e228251..ffccd9c2 100644 --- a/internal/cmd/storagebox/describe_test.go +++ b/internal/cmd/storagebox/describe_test.go @@ -80,7 +80,7 @@ func TestDescribe(t *testing.T) { }, Server: hcloud.Ptr("u1337.your-storagebox.de"), System: hcloud.Ptr("FSN1-BX355"), - Stats: &hcloud.StorageBoxStats{ + Stats: hcloud.StorageBoxStats{ Size: 0, SizeData: 0, SizeSnapshots: 0, diff --git a/internal/cmd/storagebox/list_test.go b/internal/cmd/storagebox/list_test.go index d512e4c0..c6c2fdcb 100644 --- a/internal/cmd/storagebox/list_test.go +++ b/internal/cmd/storagebox/list_test.go @@ -33,7 +33,7 @@ func TestList(t *testing.T) { StorageBoxType: &hcloud.StorageBoxType{ Name: "bx11", }, - Stats: &hcloud.StorageBoxStats{ + Stats: hcloud.StorageBoxStats{ Size: 42 * util.Gibibyte, }, Labels: map[string]string{ @@ -59,6 +59,7 @@ func TestList(t *testing.T) { AllWithOpts( gomock.Any(), hcloud.StorageBoxListOpts{ + Sort: []string{"id:asc"}, ListOpts: hcloud.ListOpts{PerPage: 50}, }, ). diff --git a/internal/cmd/storagebox/snapshot/list_test.go b/internal/cmd/storagebox/snapshot/list_test.go index d7c9adc3..197c966f 100644 --- a/internal/cmd/storagebox/snapshot/list_test.go +++ b/internal/cmd/storagebox/snapshot/list_test.go @@ -53,7 +53,7 @@ func TestList(t *testing.T) { AllSnapshotsWithOpts( gomock.Any(), sb, - hcloud.StorageBoxSnapshotListOpts{}, + hcloud.StorageBoxSnapshotListOpts{Sort: []string{"id:asc"}}, ). Return([]*hcloud.StorageBoxSnapshot{ sbs, diff --git a/internal/cmd/storagebox/subaccount/change_home_directory_test.go b/internal/cmd/storagebox/subaccount/change_home_directory_test.go index 3f1518ca..a8afb084 100644 --- a/internal/cmd/storagebox/subaccount/change_home_directory_test.go +++ b/internal/cmd/storagebox/subaccount/change_home_directory_test.go @@ -26,7 +26,7 @@ func TestChangeHomeDirectory(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(456)). + GetSubaccount(gomock.Any(), sb, "456"). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). ChangeSubaccountHomeDirectory(gomock.Any(), sbs, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ diff --git a/internal/cmd/storagebox/subaccount/delete_test.go b/internal/cmd/storagebox/subaccount/delete_test.go index 1331912d..dc13ead0 100644 --- a/internal/cmd/storagebox/subaccount/delete_test.go +++ b/internal/cmd/storagebox/subaccount/delete_test.go @@ -33,7 +33,7 @@ func TestDelete(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(456)). + GetSubaccount(gomock.Any(), sb, "456"). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). DeleteSubaccount(gomock.Any(), sbs). @@ -63,7 +63,7 @@ func TestDeleteMultiple(t *testing.T) { Name: "my-storage-box", } - snapshots := []*hcloud.StorageBoxSubaccount{ + subaccounts := []*hcloud.StorageBoxSubaccount{ { ID: 123, StorageBox: sb, @@ -83,10 +83,11 @@ func TestDeleteMultiple(t *testing.T) { Return(sb, nil, nil) var ids []string - for _, sbs := range snapshots { - ids = append(ids, strconv.FormatInt(sbs.ID, 10)) + for _, sbs := range subaccounts { + idStr := strconv.FormatInt(sbs.ID, 10) + ids = append(ids, idStr) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, sbs.ID). + GetSubaccount(gomock.Any(), sb, idStr). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). DeleteSubaccount(gomock.Any(), sbs). diff --git a/internal/cmd/storagebox/subaccount/describe_test.go b/internal/cmd/storagebox/subaccount/describe_test.go index e754c440..75e7e88e 100644 --- a/internal/cmd/storagebox/subaccount/describe_test.go +++ b/internal/cmd/storagebox/subaccount/describe_test.go @@ -54,7 +54,7 @@ func TestDescribe(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(42)). + GetSubaccount(gomock.Any(), sb, "42"). Return(sbs, nil, nil) out, errOut, err := fx.Run(cmd, []string{"my-storage-box", "42"}) diff --git a/internal/cmd/storagebox/subaccount/list_test.go b/internal/cmd/storagebox/subaccount/list_test.go index d1829d12..0000facd 100644 --- a/internal/cmd/storagebox/subaccount/list_test.go +++ b/internal/cmd/storagebox/subaccount/list_test.go @@ -57,7 +57,7 @@ func TestList(t *testing.T) { AllSubaccountsWithOpts( gomock.Any(), sb, - hcloud.StorageBoxSubaccountListOpts{}, + hcloud.StorageBoxSubaccountListOpts{Sort: []string{"id:asc"}}, ). Return([]*hcloud.StorageBoxSubaccount{ sbs, diff --git a/internal/cmd/storagebox/subaccount/reset_password_test.go b/internal/cmd/storagebox/subaccount/reset_password_test.go index d2f00cd9..01e70113 100644 --- a/internal/cmd/storagebox/subaccount/reset_password_test.go +++ b/internal/cmd/storagebox/subaccount/reset_password_test.go @@ -26,7 +26,7 @@ func TestResetPassword(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(456)). + GetSubaccount(gomock.Any(), sb, "456"). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). ResetSubaccountPassword(gomock.Any(), sbs, hcloud.StorageBoxSubaccountResetPasswordOpts{Password: "new-password"}). diff --git a/internal/cmd/storagebox/subaccount/update_access_settings_test.go b/internal/cmd/storagebox/subaccount/update_access_settings_test.go index 1f485110..4efc666b 100644 --- a/internal/cmd/storagebox/subaccount/update_access_settings_test.go +++ b/internal/cmd/storagebox/subaccount/update_access_settings_test.go @@ -26,7 +26,7 @@ func TestUpdateAccessSettings(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(456)). + GetSubaccount(gomock.Any(), sb, "456"). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). UpdateSubaccountAccessSettings(gomock.Any(), sbs, hcloud.StorageBoxSubaccountAccessSettingsUpdateOpts{ @@ -41,7 +41,7 @@ func TestUpdateAccessSettings(t *testing.T) { WaitForActions(gomock.Any(), gomock.Any(), &hcloud.Action{ID: 456}). Return(nil) - args := []string{"my-storage-box", "456", "--enable-ssh", "--enable-webdav=false", "--readonly=true", "--home-directory", "/new/home"} + args := []string{"my-storage-box", "456", "--enable-ssh", "--enable-webdav=false", "--readonly=true"} out, errOut, err := fx.Run(cmd, args) require.NoError(t, err) diff --git a/internal/cmd/storagebox/subaccount/update_test.go b/internal/cmd/storagebox/subaccount/update_test.go index f45bc373..44ba5793 100644 --- a/internal/cmd/storagebox/subaccount/update_test.go +++ b/internal/cmd/storagebox/subaccount/update_test.go @@ -32,7 +32,7 @@ func TestUpdate(t *testing.T) { Get(gomock.Any(), "my-storage-box"). Return(sb, nil, nil) fx.Client.StorageBoxClient.EXPECT(). - GetSubaccountByID(gomock.Any(), sb, int64(456)). + GetSubaccount(gomock.Any(), sb, "456"). Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). UpdateSubaccount(gomock.Any(), sbs, hcloud.StorageBoxSubaccountUpdateOpts{ diff --git a/internal/cmd/storagebox/update_test.go b/internal/cmd/storagebox/update_test.go index 49491dfb..7d5a48ee 100644 --- a/internal/cmd/storagebox/update_test.go +++ b/internal/cmd/storagebox/update_test.go @@ -24,7 +24,7 @@ func TestUpdateName(t *testing.T) { Return(&hcloud.StorageBox{ID: 123}, nil, nil) fx.Client.StorageBoxClient.EXPECT(). Update(gomock.Any(), &hcloud.StorageBox{ID: 123}, hcloud.StorageBoxUpdateOpts{ - Name: "new-name", + Name: hcloud.Ptr("new-name"), }) out, errOut, err := fx.Run(cmd, []string{"123", "--name", "new-name"}) From 81ea323ba7ab08d64afb33830f1b70da1606f005 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 15:40:32 +0200 Subject: [PATCH 12/17] HomeDirectory not a pointer anymore --- internal/cmd/storagebox/subaccount/change_home_directory.go | 2 +- .../cmd/storagebox/subaccount/change_home_directory_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/storagebox/subaccount/change_home_directory.go b/internal/cmd/storagebox/subaccount/change_home_directory.go index 743ec96b..b107216f 100644 --- a/internal/cmd/storagebox/subaccount/change_home_directory.go +++ b/internal/cmd/storagebox/subaccount/change_home_directory.go @@ -52,7 +52,7 @@ var ChangeHomeDirectoryCmd = base.Cmd{ } action, _, err := s.Client().StorageBox().ChangeSubaccountHomeDirectory(s, subaccount, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ - HomeDirectory: &homeDirectory, + HomeDirectory: homeDirectory, }) if err != nil { return err diff --git a/internal/cmd/storagebox/subaccount/change_home_directory_test.go b/internal/cmd/storagebox/subaccount/change_home_directory_test.go index a8afb084..d3d1c77e 100644 --- a/internal/cmd/storagebox/subaccount/change_home_directory_test.go +++ b/internal/cmd/storagebox/subaccount/change_home_directory_test.go @@ -30,7 +30,7 @@ func TestChangeHomeDirectory(t *testing.T) { Return(sbs, nil, nil) fx.Client.StorageBoxClient.EXPECT(). ChangeSubaccountHomeDirectory(gomock.Any(), sbs, hcloud.StorageBoxSubaccountChangeHomeDirectoryOpts{ - HomeDirectory: hcloud.Ptr("/new/home"), + HomeDirectory: "/new/home", }). Return(&hcloud.Action{ID: 456}, nil, nil) fx.ActionWaiter.EXPECT(). From c1289d6ee30ccad7a9646c07731c4221973c5511 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:37:58 +0200 Subject: [PATCH 13/17] go generate --- docs/reference/manual/hcloud_zone.md | 1 + docs/reference/manual/hcloud_zone_add-label.md | 1 + docs/reference/manual/hcloud_zone_add-records.md | 1 + docs/reference/manual/hcloud_zone_change-primary-nameservers.md | 1 + docs/reference/manual/hcloud_zone_change-ttl.md | 1 + docs/reference/manual/hcloud_zone_create.md | 1 + docs/reference/manual/hcloud_zone_delete.md | 1 + docs/reference/manual/hcloud_zone_describe.md | 1 + docs/reference/manual/hcloud_zone_disable-protection.md | 1 + docs/reference/manual/hcloud_zone_enable-protection.md | 1 + docs/reference/manual/hcloud_zone_export-zonefile.md | 1 + docs/reference/manual/hcloud_zone_import-zonefile.md | 1 + docs/reference/manual/hcloud_zone_list.md | 1 + docs/reference/manual/hcloud_zone_remove-label.md | 1 + docs/reference/manual/hcloud_zone_remove-records.md | 1 + docs/reference/manual/hcloud_zone_rrset.md | 1 + docs/reference/manual/hcloud_zone_rrset_add-label.md | 1 + docs/reference/manual/hcloud_zone_rrset_add-records.md | 1 + docs/reference/manual/hcloud_zone_rrset_change-ttl.md | 1 + docs/reference/manual/hcloud_zone_rrset_create.md | 1 + docs/reference/manual/hcloud_zone_rrset_delete.md | 1 + docs/reference/manual/hcloud_zone_rrset_describe.md | 1 + docs/reference/manual/hcloud_zone_rrset_disable-protection.md | 1 + docs/reference/manual/hcloud_zone_rrset_enable-protection.md | 1 + docs/reference/manual/hcloud_zone_rrset_list.md | 1 + docs/reference/manual/hcloud_zone_rrset_remove-label.md | 1 + docs/reference/manual/hcloud_zone_rrset_remove-records.md | 1 + docs/reference/manual/hcloud_zone_rrset_set-records.md | 1 + docs/reference/manual/hcloud_zone_set-records.md | 1 + 29 files changed, 29 insertions(+) diff --git a/docs/reference/manual/hcloud_zone.md b/docs/reference/manual/hcloud_zone.md index 8358e66d..448550aa 100644 --- a/docs/reference/manual/hcloud_zone.md +++ b/docs/reference/manual/hcloud_zone.md @@ -24,6 +24,7 @@ See https://docs.hetzner.cloud/changelog#2025-10-07-dns-beta for more details. --debug Enable debug output --debug-file string File to write debug output to --endpoint string Hetzner Cloud API endpoint (default "https://api.hetzner.cloud/v1") + --hetzner-endpoint string Hetzner API endpoint (default "https://api.hetzner.com/v1") --no-experimental-warnings If true, experimental warnings are not shown --poll-interval duration Interval at which to poll information, for example action progress (default 500ms) --quiet If true, only print error messages diff --git a/docs/reference/manual/hcloud_zone_add-label.md b/docs/reference/manual/hcloud_zone_add-label.md index e383bc43..ddf1e899 100644 --- a/docs/reference/manual/hcloud_zone_add-label.md +++ b/docs/reference/manual/hcloud_zone_add-label.md @@ -29,6 +29,7 @@ hcloud zone add-label [--overwrite]