From 2219f1ec800474778e7e22303975cf0e4c201775 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Mon, 3 Oct 2022 13:51:55 +0200 Subject: [PATCH] blind_update: Allow parallel updating --- cmd/blind_update.go | 53 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/cmd/blind_update.go b/cmd/blind_update.go index 5d9dd82..a6e7434 100644 --- a/cmd/blind_update.go +++ b/cmd/blind_update.go @@ -1,16 +1,24 @@ package cmd import ( + "fmt" + "io" + wisski_distillery "github.com/FAU-CDI/wisski-distillery" + "github.com/FAU-CDI/wisski-distillery/internal/component/instances" "github.com/FAU-CDI/wisski-distillery/internal/core" "github.com/FAU-CDI/wisski-distillery/pkg/environment" + "github.com/FAU-CDI/wisski-distillery/pkg/slicesx" "github.com/tkw1536/goprogram/exit" + "github.com/tkw1536/goprogram/status" + "github.com/tkw1536/goprogram/stream" ) // BlindUpdate is the 'blind_update' command var BlindUpdate wisski_distillery.Command = blindUpdate{} type blindUpdate struct { + Parallel int `short:"p" long:"parallel" description:"run on (at most) this many instances concurrently. 0 for no limit." default:"1"` Force bool `short:"f" long:"force" description:"force running blind-update even if AutoBlindUpdate is set to false"` Positionals struct { Slug []string `positional-arg-name:"SLUG" required:"0" description:"slug of instance(s) to run blind-update in"` @@ -33,16 +41,48 @@ var errBlindUpdateFailed = exit.Error{ } func (bu blindUpdate) Run(context wisski_distillery.Context) error { - instances, err := context.Environment.Instances().Load(bu.Positionals.Slug...) + wissKIs, err := context.Environment.Instances().Load(bu.Positionals.Slug...) if err != nil { return err } + if !bu.Force { + wissKIs = slicesx.Filter(wissKIs, func(instance instances.WissKI) bool { + return bool(instance.AutoBlindUpdateEnabled) + }) + } - for _, instance := range instances { - if !(instance.IsBlindUpdateEnabled() || bu.Force) { - context.EPrintf("skipping instance %q\n", instance.Slug) - continue - } + if bu.Parallel == 1 { + return bu.runSequential(wissKIs, context) + } + + return bu.runParallel(wissKIs, context) +} + +func (bu blindUpdate) runParallel(wissKIs []instances.WissKI, context wisski_distillery.Context) error { + return status.RunErrorGroup(context.Stdout, status.Group[instances.WissKI, error]{ + PrefixString: func(item instances.WissKI, index int) string { + return fmt.Sprintf("[instance %q]: ", item.Slug) + }, + PrefixAlign: true, + + Handler: func(instance instances.WissKI, index int, writer io.Writer) error { + io := stream.NewIOStream(writer, writer, nil, 0) + + code, err := instance.Shell(io, "/runtime/blind_update.sh") + if err != nil { + return errBlindUpdateFailed.WithMessageF(instance.Slug, environment.ExecCommandError) + } + if code != 0 { + return errBlindUpdateFailed.WithMessageF(instance.Slug, code) + } + return nil + }, + HandlerLimit: bu.Parallel, + }, wissKIs) +} + +func (bu blindUpdate) runSequential(wissKIs []instances.WissKI, context wisski_distillery.Context) error { + for _, instance := range wissKIs { context.EPrintf("Updating instance %s\n", instance.Slug) code, err := instance.Shell(context.IOStream, "/runtime/blind_update.sh") @@ -53,6 +93,5 @@ func (bu blindUpdate) Run(context wisski_distillery.Context) error { return errBlindUpdateFailed.WithMessageF(instance.Slug, code) } } - return nil }