From f40ab57ed1aa331f28c57522016e62e3991753b0 Mon Sep 17 00:00:00 2001 From: Tommy-Lee Bannert <58707896+bannert1337@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:45:14 +0200 Subject: [PATCH 1/6] feat(batchops): add batch processing for adding labels to multiple resources Add support for processing multiple resources in parallel when adding labels, improving efficiency for bulk operations. Includes batch fetching, validation, and result display with error handling. Uses configurable batch size and goroutines for concurrent processing. --- internal/cmd/base/labels.go | 222 +++++++++++++++++++++++++++++++++++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/internal/cmd/base/labels.go b/internal/cmd/base/labels.go index cee35c18..be4acc9a 100644 --- a/internal/cmd/base/labels.go +++ b/internal/cmd/base/labels.go @@ -4,8 +4,10 @@ import ( "errors" "fmt" "log" + "maps" "slices" "strings" + "sync" "github.com/spf13/cobra" @@ -15,6 +17,20 @@ import ( "github.com/hetznercloud/cli/internal/state" ) +// labelBatchSize is the batch size when processing multiple resources in parallel. +const labelBatchSize = 10 + +// BatchLabelResult represents the result of a batch label operation for a single resource. +type BatchLabelResult struct { + IDOrName string + Resource interface{} + Success bool + Error error + LabelsAdded []string + LabelsRemoved []string + AllLabelsRemoved bool +} + // LabelCmds allows defining commands for adding labels to resources. type LabelCmds[T any] struct { ResourceNameSingular string @@ -48,6 +64,10 @@ type LabelCmds[T any] struct { // Experimental is a function that will be used to mark the command as experimental. Experimental func(state.State, *cobra.Command) *cobra.Command + + // Batch operation support + FetchBatch func(s state.State, idOrNames []string) ([]T, []error) + SetLabelsBatch func(s state.State, resources []T, labels map[string]string) []error } // AddCobraCommand creates a command that can be registered with cobra. @@ -65,15 +85,15 @@ func (lc *LabelCmds[T]) AddCobraCommand(s state.State) *cobra.Command { } cmd := &cobra.Command{ - Use: fmt.Sprintf("add-label [--overwrite] %s