Add pool balancing strategy

This change adds the ability to specify the pool balancing strategy to
use when processing queued jobs. Before this change, GARM would round-robin
through all pools that matched the set of tags requested by queued jobs.

When round-robin (default) is used for an entity (repo, org or enterprise)
and you have 2 pools defined for that entity with a common set of tags that
match 10 jobs (for example), then those jobs would trigger the creation of
a new runner in each of the two pools in turn. Job 1 would go to pool 1,
job 2 would go to pool 2, job 3 to pool 1, job 4 to pool 2 and so on.

When "stack" is used, those same 10 jobs would trigger the creation of a
new runner in the pool with the highest priority, every time.

In both cases, if a pool is full, the next one would be tried automatically.

For the stack case, this would mean that if pool 2 had a priority of 10 and
pool 1 would have a priority of 5, pool 2 would be saturated first, then
pool 1.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2024-03-14 20:04:34 +00:00
parent 569d512819
commit ce3c917ae5
34 changed files with 362 additions and 137 deletions

View file

@ -105,7 +105,7 @@ func (p *poolManagerCtrl) CreateRepoPoolManager(ctx context.Context, repo params
p.mux.Lock()
defer p.mux.Unlock()
cfgInternal, err := p.getInternalConfig(ctx, repo.CredentialsName)
cfgInternal, err := p.getInternalConfig(ctx, repo.CredentialsName, repo.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -126,7 +126,7 @@ func (p *poolManagerCtrl) UpdateRepoPoolManager(ctx context.Context, repo params
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "repository %s/%s pool manager not loaded", repo.Owner, repo.Name)
}
internalCfg, err := p.getInternalConfig(ctx, repo.CredentialsName)
internalCfg, err := p.getInternalConfig(ctx, repo.CredentialsName, repo.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -171,7 +171,7 @@ func (p *poolManagerCtrl) CreateOrgPoolManager(ctx context.Context, org params.O
p.mux.Lock()
defer p.mux.Unlock()
cfgInternal, err := p.getInternalConfig(ctx, org.CredentialsName)
cfgInternal, err := p.getInternalConfig(ctx, org.CredentialsName, org.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -192,7 +192,7 @@ func (p *poolManagerCtrl) UpdateOrgPoolManager(ctx context.Context, org params.O
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "org %s pool manager not loaded", org.Name)
}
internalCfg, err := p.getInternalConfig(ctx, org.CredentialsName)
internalCfg, err := p.getInternalConfig(ctx, org.CredentialsName, org.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -237,7 +237,7 @@ func (p *poolManagerCtrl) CreateEnterprisePoolManager(ctx context.Context, enter
p.mux.Lock()
defer p.mux.Unlock()
cfgInternal, err := p.getInternalConfig(ctx, enterprise.CredentialsName)
cfgInternal, err := p.getInternalConfig(ctx, enterprise.CredentialsName, enterprise.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -258,7 +258,7 @@ func (p *poolManagerCtrl) UpdateEnterprisePoolManager(ctx context.Context, enter
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "enterprise %s pool manager not loaded", enterprise.Name)
}
internalCfg, err := p.getInternalConfig(ctx, enterprise.CredentialsName)
internalCfg, err := p.getInternalConfig(ctx, enterprise.CredentialsName, enterprise.GetBalancerType())
if err != nil {
return nil, errors.Wrap(err, "fetching internal config")
}
@ -299,7 +299,7 @@ func (p *poolManagerCtrl) GetEnterprisePoolManagers() (map[string]common.PoolMan
return p.enterprises, nil
}
func (p *poolManagerCtrl) getInternalConfig(ctx context.Context, credsName string) (params.Internal, error) {
func (p *poolManagerCtrl) getInternalConfig(ctx context.Context, credsName string, poolBalancerType params.PoolBalancerType) (params.Internal, error) {
creds, ok := p.credentials[credsName]
if !ok {
return params.Internal{}, runnerErrors.NewBadRequestError("invalid credential name (%s)", credsName)
@ -325,6 +325,7 @@ func (p *poolManagerCtrl) getInternalConfig(ctx context.Context, credsName strin
BaseWebhookURL: p.config.Default.WebhookURL,
ControllerWebhookURL: controllerWebhookURL,
JWTSecret: p.config.JWTAuth.Secret,
PoolBalancerType: poolBalancerType,
GithubCredentialsDetails: params.GithubCredentials{
Name: creds.Name,
Description: creds.Description,