func (h *HatcheryLocal) SpawnWorker(ctx context.Context, spawnArgs hatchery.SpawnArguments) error {
	log.Debug(ctx, "HatcheryLocal.SpawnWorker> %s want to spawn a worker named %s (jobID = %d)", spawnArgs.HatcheryName, spawnArgs.WorkerName, spawnArgs.JobID)

	if spawnArgs.JobID == 0 && !spawnArgs.RegisterOnly {
		return sdk.WithStack(fmt.Errorf("no job ID and no register"))
	}

	// Generate a random string 16 chars length
	bs := make([]byte, 16)
	if _, err := rand.Read(bs); err != nil {
		return err
	}
	rndstr := hex.EncodeToString(bs)[0:16]
	basedir := path.Join(h.Config.Basedir, rndstr)
	// Create the directory
	if err := os.MkdirAll(basedir, os.FileMode(0755)); err != nil {
		return err
	}

	log.Info(ctx, "HatcheryLocal.SpawnWorker> basedir: %s", basedir)

	udataParam := h.GenerateWorkerArgs(h, spawnArgs)
	udataParam.BaseDir = basedir
	udataParam.WorkerBinary = path.Join(h.BasedirDedicated, h.getWorkerBinaryName())
	udataParam.WorkflowJobID = spawnArgs.JobID

	tmpl, errt := template.New("cmd").Parse(workerCmdTmpl)
	if errt != nil {
		return errt
	}
	var buffer bytes.Buffer
	if errTmpl := tmpl.Execute(&buffer, udataParam); errTmpl != nil {
		return errTmpl
	}

	cmdSplitted := strings.Split(buffer.String(), " -")
	for i := range cmdSplitted[1:] {
		cmdSplitted[i+1] = "-" + strings.Trim(cmdSplitted[i+1], " ")
	}

	// Prefix the command with the directory where the worker binary has been downloaded
	log.Debug(ctx, "Command exec: %v", cmdSplitted)
	var cmd *exec.Cmd
	if spawnArgs.RegisterOnly {
		cmdSplitted[0] = "register"
		cmd = h.LocalWorkerRunner.NewCmd(ctx, cmdSplitted[0], cmdSplitted...)
	} else {
		cmd = h.LocalWorkerRunner.NewCmd(ctx, cmdSplitted[0], cmdSplitted[1:]...)
	}

	cmd.Dir = udataParam.BaseDir

	// Clearenv
	env := os.Environ()
	for _, e := range env {
		if !strings.HasPrefix(e, "CDS") && !strings.HasPrefix(e, "HATCHERY") {
			cmd.Env = append(cmd.Env, e)
		}
	}

	// Wait in a goroutine so that when process exits, Wait() update cmd.ProcessState
	go func() {
		log.Debug(ctx, "hatchery> local> starting worker: %s", spawnArgs.WorkerName)
		if err := h.startCmd(spawnArgs.WorkerName, cmd, localWorkerLogger{spawnArgs.WorkerName}); err != nil {
			log.Error(ctx, "hatchery> local> %v", err)
		}
	}()

	return nil
}
// SpawnWorker starts a new worker process
SpawnWorker starts a new worker process
// SpawnWorker starts a new worker process
func (h *HatcheryLocal) SpawnWorker(ctx context.Context, spawnArgs hatchery.SpawnArguments) error {
	log.Debug(ctx, "HatcheryLocal.SpawnWorker> %s want to spawn a worker named %s (jobID = %d)", spawnArgs.HatcheryName, spawnArgs.WorkerName, spawnArgs.JobID)
	if spawnArgs.JobID == 0 && !spawnArgs.RegisterOnly {
		return sdk.WithStack(fmt.Errorf("no job ID and no register"))
	}
	bs := make([]byte, 16)
	if _, err := rand.Read(bs); err != nil {
		return err
	}
	rndstr := hex.EncodeToString(bs)[0:16]
	basedir := path.Join(h.Config.Basedir, rndstr)
	if err := os.MkdirAll(basedir, os.FileMode(0755)); err != nil {
		return err
	}
	log.Info(ctx, "HatcheryLocal.SpawnWorker> basedir: %s", basedir)
	udataParam := h.GenerateWorkerArgs(h, spawnArgs)
	udataParam.BaseDir = basedir
	udataParam.WorkerBinary = path.Join(h.BasedirDedicated, h.getWorkerBinaryName())
	udataParam.WorkflowJobID = spawnArgs.JobID
	tmpl, errt := template.New("cmd").Parse(workerCmdTmpl)
	if errt != nil {
		return errt
	}
	var buffer bytes.Buffer
	if errTmpl := tmpl.Execute(&buffer, udataParam); errTmpl != nil {
		return errTmpl
	}
	cmdSplitted := strings.Split(buffer.String(), " -")
	for i := range cmdSplitted[1:] {
		cmdSplitted[i+1] = "-" + strings.Trim(cmdSplitted[i+1], " ")
	}
	log.Debug(ctx, "Command exec: %v", cmdSplitted)
	var cmd *exec.Cmd
	if spawnArgs.RegisterOnly {
		cmdSplitted[0] = "register"
		cmd = h.LocalWorkerRunner.NewCmd(ctx, cmdSplitted[0], cmdSplitted...)
	} else {
		cmd = h.LocalWorkerRunner.NewCmd(ctx, cmdSplitted[0], cmdSplitted[1:]...)
	}
	cmd.Dir = udataParam.BaseDir
	env := os.Environ()
	for _, e := range env {
		if !strings.HasPrefix(e, "CDS") && !strings.HasPrefix(e, "HATCHERY") {
			cmd.Env = append(cmd.Env, e)
		}
	}
	go func() {
		log.Debug(ctx, "hatchery> local> starting worker: %s", spawnArgs.WorkerName)
		if err := h.startCmd(spawnArgs.WorkerName, cmd, localWorkerLogger{spawnArgs.WorkerName}); err != nil {
			log.Error(ctx, "hatchery> local> %v", err)
		}
	}()
	return nil
}
func ( h * HatcheryLocal ) SpawnWorker ( ctx context . Context , spawnArgs hatchery . SpawnArguments ) error { log . Debug ( ctx , " " , spawnArgs . HatcheryName , spawnArgs . WorkerName , spawnArgs . JobID ) if spawnArgs . JobID == 0 && ! spawnArgs . RegisterOnly { return sdk . WithStack ( fmt . Errorf ( " " ) ) } bs := make ( [ ] byte , 16 ) if _ , err := rand . Read ( bs ) ; err != nil { return err } rndstr := hex . EncodeToString ( bs ) [ 0 : 16 ] basedir := path . Join ( h . Config . Basedir , rndstr ) if err := os . MkdirAll ( basedir , os . FileMode ( 0755 ) ) ; err != nil { return err } log . Info ( ctx , " " , basedir ) udataParam := h . GenerateWorkerArgs ( h , spawnArgs ) udataParam . BaseDir = basedir udataParam . WorkerBinary = path . Join ( h . BasedirDedicated , h . getWorkerBinaryName ( ) ) udataParam . WorkflowJobID = spawnArgs . JobID tmpl , errt := template . New ( " " ) . Parse ( workerCmdTmpl ) if errt != nil { return errt } var buffer bytes . Buffer if errTmpl := tmpl . Execute ( & buffer , udataParam ) ; errTmpl != nil { return errTmpl } cmdSplitted := strings . Split ( buffer . String ( ) , " " ) for i := range cmdSplitted [ 1 : ] { cmdSplitted [ i + 1 ] = " " + strings . Trim ( cmdSplitted [ i + 1 ] , " " ) } log . Debug ( ctx , " " , cmdSplitted ) var cmd * exec . Cmd if spawnArgs . RegisterOnly { cmdSplitted [ 0 ] = " " cmd = h . LocalWorkerRunner . NewCmd ( ctx , cmdSplitted [ 0 ] , cmdSplitted ... ) } else { cmd = h . LocalWorkerRunner . NewCmd ( ctx , cmdSplitted [ 0 ] , cmdSplitted [ 1 : ] ... ) } cmd . Dir = udataParam . BaseDir env := os . Environ ( ) for _ , e := range env { if ! strings . HasPrefix ( e , " " ) && ! strings . HasPrefix ( e , " " ) { cmd . Env = append ( cmd . Env , e ) } } go func ( ) { log . Debug ( ctx , " " , spawnArgs . WorkerName ) if err := h . startCmd ( spawnArgs . WorkerName , cmd , localWorkerLogger { spawnArgs . WorkerName } ) ; err != nil { log . Error ( ctx , " " , err ) } } ( ) return nil }
SpawnWorker starts a new worker process
SpawnWorker starts a new worker process
// Generate a random string 16 chars length // Create the directory // Prefix the command with the directory where the worker binary has been downloaded // Clearenv // Wait in a goroutine so that when process exits, Wait() update cmd.ProcessState