From 9348153cb02a7fe95f39e726eac26cb68222f513 Mon Sep 17 00:00:00 2001 From: Nikolay Edigaryev Date: Wed, 28 Jan 2026 11:58:28 +0100 Subject: [PATCH] orchard worker run: introduce "--synthetic" and "--workers" hidden flags --- internal/command/dev/dev.go | 12 +--- internal/command/worker/run.go | 65 ++++++++++++++++--- internal/worker/option.go | 6 ++ .../iokitregistry/iokitregistry.go | 3 +- .../iokitregistry/iokitregistry_test.go | 5 +- internal/worker/platform/platform_darwin.go | 7 ++ internal/worker/platform/platform_linux.go | 14 ++++ internal/worker/worker.go | 23 ++++--- 8 files changed, 104 insertions(+), 31 deletions(-) rename internal/worker/{ => platform}/iokitregistry/iokitregistry.go (99%) rename internal/worker/{ => platform}/iokitregistry/iokitregistry_test.go (80%) create mode 100644 internal/worker/platform/platform_darwin.go create mode 100644 internal/worker/platform/platform_linux.go diff --git a/internal/command/dev/dev.go b/internal/command/dev/dev.go index 6977182..7f80f91 100644 --- a/internal/command/dev/dev.go +++ b/internal/command/dev/dev.go @@ -142,21 +142,15 @@ func runDev(cmd *cobra.Command, args []string) error { return devController.Run(ctx) }) - workerName, err := worker.DefaultName() - if err != nil { - return err - } - for i := range workers { group.Go(func() error { - workerNameLocal := workerName + workerOptsLocal := additionalWorkerOpts if workers > 1 { - workerNameLocal = fmt.Sprintf("%s-%d", workerName, i) + workerOptsLocal = append(workerOptsLocal, worker.WithNameSuffix(fmt.Sprintf("-%d", i+1))) } - devWorker, err := CreateDevWorker(devClient, resources, - append(additionalWorkerOpts, worker.WithName(workerNameLocal)), logger) + devWorker, err := CreateDevWorker(devClient, resources, workerOptsLocal, logger) if err != nil { return err } diff --git a/internal/command/worker/run.go b/internal/command/worker/run.go index 87752f4..0e5db39 100644 --- a/internal/command/worker/run.go +++ b/internal/command/worker/run.go @@ -17,6 +17,7 @@ import ( "github.com/cirruslabs/chacha/pkg/privdrop" "github.com/cirruslabs/orchard/internal/bootstraptoken" "github.com/cirruslabs/orchard/internal/dialer" + "github.com/cirruslabs/orchard/internal/echoserver" "github.com/cirruslabs/orchard/internal/netconstants" "github.com/cirruslabs/orchard/internal/worker" "github.com/cirruslabs/orchard/pkg/client" @@ -24,6 +25,7 @@ import ( "github.com/spf13/cobra" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "golang.org/x/sync/errgroup" "gopkg.in/natefinch/lumberjack.v2" ) @@ -46,6 +48,10 @@ var username string var addressPprof string var debug bool +// Hidden flags +var synthetic bool +var workers int + func newRunCommand() *cobra.Command { cmd := &cobra.Command{ Use: "run CONTROLLER_URL", @@ -82,6 +88,14 @@ func newRunCommand() *cobra.Command { "start pprof HTTP server on localhost:6060 for diagnostic purposes (e.g. \"localhost:6060\")") cmd.Flags().BoolVar(&debug, "debug", false, "enable debug logging") + // Hidden flags + cmd.Flags().BoolVar(&synthetic, "synthetic", false, + "do not instantiate real Tart VM, use synthetic in-memory VMs suitable for load testing") + cmd.Flags().MarkHidden("synthetic") + + cmd.Flags().IntVar(&workers, "workers", 1, "number of workers to start") + cmd.Flags().MarkHidden("workers") + return cmd } @@ -175,16 +189,49 @@ func runWorker(cmd *cobra.Command, args []string) (err error) { }() } - workerInstance, err := worker.New( - controllerClient, - workerOpts..., - ) - if err != nil { - return err - } - defer workerInstance.Close() + group, ctx := errgroup.WithContext(cmd.Context()) - return workerInstance.Run(cmd.Context()) + if synthetic { + // Use TCP echo server to partially emulate VM's TCP/IP stack, + // this way we get port-forwarding working when running in + // synthetic mode + echoServer, err := echoserver.New() + if err != nil { + return err + } + + group.Go(func() error { + return echoServer.Run(ctx) + }) + + dialer := dialer.DialFunc(func(ctx context.Context, network, addr string) (net.Conn, error) { + dialer := net.Dialer{} + + return dialer.DialContext(ctx, "tcp", echoServer.Addr()) + }) + + workerOpts = append(workerOpts, worker.WithSynthetic(), worker.WithDialer(dialer)) + } + + for i := range workers { + group.Go(func() error { + workerOptsLocal := workerOpts + + if workers > 1 { + workerOptsLocal = append(workerOptsLocal, worker.WithNameSuffix(fmt.Sprintf("-%d", i+1))) + } + + workerInstance, err := worker.New(controllerClient, workerOptsLocal...) + if err != nil { + return err + } + defer workerInstance.Close() + + return workerInstance.Run(cmd.Context()) + }) + } + + return group.Wait() } func readBootstrapToken() (string, error) { diff --git a/internal/worker/option.go b/internal/worker/option.go index 404c38a..50378bf 100644 --- a/internal/worker/option.go +++ b/internal/worker/option.go @@ -14,6 +14,12 @@ func WithName(name string) Option { } } +func WithNameSuffix(nameSuffix string) Option { + return func(worker *Worker) { + worker.nameSuffix = nameSuffix + } +} + func WithResources(resources v1.Resources) Option { return func(worker *Worker) { worker.resources = resources diff --git a/internal/worker/iokitregistry/iokitregistry.go b/internal/worker/platform/iokitregistry/iokitregistry.go similarity index 99% rename from internal/worker/iokitregistry/iokitregistry.go rename to internal/worker/platform/iokitregistry/iokitregistry.go index 738561b..151cc60 100644 --- a/internal/worker/iokitregistry/iokitregistry.go +++ b/internal/worker/platform/iokitregistry/iokitregistry.go @@ -3,8 +3,9 @@ package iokitregistry import ( "errors" "fmt" - "howett.net/plist" "os/exec" + + "howett.net/plist" ) var ErrFailed = errors.New("failed to query I/O Kit registry") diff --git a/internal/worker/iokitregistry/iokitregistry_test.go b/internal/worker/platform/iokitregistry/iokitregistry_test.go similarity index 80% rename from internal/worker/iokitregistry/iokitregistry_test.go rename to internal/worker/platform/iokitregistry/iokitregistry_test.go index 9955447..4397926 100644 --- a/internal/worker/iokitregistry/iokitregistry_test.go +++ b/internal/worker/platform/iokitregistry/iokitregistry_test.go @@ -1,10 +1,11 @@ package iokitregistry_test import ( - "github.com/cirruslabs/orchard/internal/worker/iokitregistry" + "testing" + + "github.com/cirruslabs/orchard/internal/worker/platform/iokitregistry" "github.com/google/uuid" "github.com/stretchr/testify/require" - "testing" ) func TestPlatformUUID(t *testing.T) { diff --git a/internal/worker/platform/platform_darwin.go b/internal/worker/platform/platform_darwin.go new file mode 100644 index 0000000..8b3126f --- /dev/null +++ b/internal/worker/platform/platform_darwin.go @@ -0,0 +1,7 @@ +package platform + +import "github.com/cirruslabs/orchard/internal/worker/platform/iokitregistry" + +func MachineID() (string, error) { + return iokitregistry.PlatformUUID() +} diff --git a/internal/worker/platform/platform_linux.go b/internal/worker/platform/platform_linux.go new file mode 100644 index 0000000..99c528a --- /dev/null +++ b/internal/worker/platform/platform_linux.go @@ -0,0 +1,14 @@ +package platform + +import ( + "os" +) + +func MachineID() (string, error) { + machineIDBytes, err := os.ReadFile("/etc/machine-id") + if err != nil { + return "", err + } + + return string(machineIDBytes), nil +} diff --git a/internal/worker/worker.go b/internal/worker/worker.go index 859e7fe..77136a6 100644 --- a/internal/worker/worker.go +++ b/internal/worker/worker.go @@ -12,8 +12,8 @@ import ( "github.com/cirruslabs/orchard/internal/dialer" "github.com/cirruslabs/orchard/internal/opentelemetry" "github.com/cirruslabs/orchard/internal/worker/dhcpleasetime" - "github.com/cirruslabs/orchard/internal/worker/iokitregistry" "github.com/cirruslabs/orchard/internal/worker/ondiskname" + "github.com/cirruslabs/orchard/internal/worker/platform" "github.com/cirruslabs/orchard/internal/worker/vmmanager" "github.com/cirruslabs/orchard/internal/worker/vmmanager/synthetic" "github.com/cirruslabs/orchard/internal/worker/vmmanager/tart" @@ -38,6 +38,7 @@ var ErrPollFailed = errors.New("failed to poll controller") type Worker struct { name string + nameSuffix string syncRequested chan bool vmm *vmmanager.VMManager client *client.Client @@ -72,12 +73,16 @@ func New(client *client.Client, opts ...Option) (*Worker, error) { // Apply defaults if worker.name == "" { - name, err := DefaultName() + hostname, err := os.Hostname() if err != nil { return nil, err } - worker.name = name + worker.name = hostname + } + + if worker.nameSuffix != "" { + worker.name += worker.nameSuffix } defaultResources := v1.Resources{ @@ -120,8 +125,10 @@ func New(client *client.Client, opts ...Option) (*Worker, error) { } func (worker *Worker) Run(ctx context.Context) error { - if err := dhcpleasetime.Check(); err != nil { - worker.logger.Warnf("%v", err) + if !worker.synthetic { + if err := dhcpleasetime.Check(); err != nil { + worker.logger.Warnf("%v", err) + } } for { @@ -228,12 +235,8 @@ func (worker *Worker) runNewSession(ctx context.Context) error { } } -func DefaultName() (string, error) { - return os.Hostname() -} - func (worker *Worker) registerWorker(ctx context.Context) error { - platformUUID, err := iokitregistry.PlatformUUID() + platformUUID, err := platform.MachineID() if err != nil { return err }