executors/internal/autoscaler/executor.go (45 lines of code) (raw):

package autoscaler import ( "context" "errors" "fmt" "time" "gitlab.com/gitlab-org/gitlab-runner/common" ) type executor struct { common.Executor provider *provider build *common.Build config common.RunnerConfig } func (e *executor) Prepare(options common.ExecutorPrepareOptions) (err error) { e.build = options.Build e.config = *options.Config e.build.Log().Infoln("Preparing instance...") acqRef, ok := options.Build.ExecutorData.(*acquisitionRef) if !ok { return fmt.Errorf("no acquisition ref data") } // if we already have an acquisition just retry preparing it if acqRef.acq != nil { return e.Executor.Prepare(options) } // The acqTimeout defines how long we are willing to wait for an instance to be acquired. // It defaults to 15 minutes, as cloud providers can take several minutes to provision instances, // especially for certain operating systems like Windows. This value can be configured // through the Autoscaler configuration (InstanceAcquireTimeout) to better suit the user's environment. acqTimeout := 15 * time.Minute if options.Config.Autoscaler != nil && options.Config.Autoscaler.InstanceAcquireTimeout > 0 { acqTimeout = options.Config.Autoscaler.InstanceAcquireTimeout } ctx, cancel := context.WithTimeout(options.Context, acqTimeout) defer cancel() acq, err := e.provider.getRunnerTaskscaler(options.Config).Acquire(ctx, acqRef.key) if err != nil { // Check if the error is due to the context timeout if errors.Is(err, context.DeadlineExceeded) { return fmt.Errorf("unable to acquire instance within the configured timeout of %s: %w", acqTimeout, err) } return fmt.Errorf("unable to acquire instance: %w", err) } e.build.Log().WithField("key", acqRef.key).Trace("Acquired capacity...") acqRef.acq = acq return e.Executor.Prepare(options) } func (e *executor) Cleanup() { e.Executor.Cleanup() }