Handle org runners

This commit is contained in:
Gabriel Adrian Samfira 2022-04-22 14:46:27 +00:00
parent bf0a5bf147
commit ebec0dda52
18 changed files with 1028 additions and 184 deletions

View file

@ -1 +0,0 @@
package pool

46
runner/pool/repository.go Normal file
View file

@ -0,0 +1,46 @@
package pool
import (
"context"
"runner-manager/config"
"runner-manager/params"
"runner-manager/runner/common"
"github.com/google/go-github/v43/github"
)
func NewRepositoryRunnerPool(ctx context.Context, cfg config.Repository, ghcli *github.Client, provider common.Provider) (common.PoolManager, error) {
return &Repository{
ctx: ctx,
cfg: cfg,
ghcli: ghcli,
provider: provider,
}, nil
}
type Repository struct {
ctx context.Context
cfg config.Repository
ghcli *github.Client
provider common.Provider
}
func (r *Repository) getGithubRunners() ([]github.Runner, error) {
return nil, nil
}
func (r *Repository) getProviderInstances() ([]params.Instance, error) {
return nil, nil
}
func (r *Repository) Start() error {
return nil
}
func (r *Repository) Stop() error {
return nil
}
func (r *Repository) loop() {
}

View file

@ -3,9 +3,7 @@ package lxd
import (
"context"
"fmt"
"strings"
"runner-manager/cloudconfig"
"runner-manager/config"
runnerErrors "runner-manager/errors"
"runner-manager/params"
@ -47,6 +45,12 @@ var (
config.Arm64: "aarch64",
config.Arm: "armv7l",
}
lxdToConfigArch map[string]config.OSArch = map[string]config.OSArch{
"x86_64": config.Amd64,
"aarch64": config.Arm64,
"armv7l": config.Arm,
}
)
const (
@ -54,22 +58,15 @@ const (
DefaultProjectName = "runner-manager-project"
)
func NewProvider(ctx context.Context, cfg *config.Provider, pool *config.Pool, controllerID string) (common.Provider, error) {
func NewProvider(ctx context.Context, cfg *config.Provider, controllerID string) (common.Provider, error) {
if err := cfg.Validate(); err != nil {
return nil, errors.Wrap(err, "validating provider config")
}
if err := pool.Validate(); err != nil {
return nil, errors.Wrap(err, "validating pool")
}
if cfg.ProviderType != config.LXDProvider {
return nil, fmt.Errorf("invalid provider type %s, expected %s", cfg.ProviderType, config.LXDProvider)
}
if cfg.Name != pool.ProviderName {
return nil, fmt.Errorf("provider %s is not responsible for pool", cfg.Name)
}
cli, err := getClientFromConfig(ctx, &cfg.LXD)
if err != nil {
return nil, errors.Wrap(err, "creating LXD client")
@ -84,7 +81,6 @@ func NewProvider(ctx context.Context, cfg *config.Provider, pool *config.Pool, c
provider := &LXD{
ctx: ctx,
cfg: cfg,
pool: pool,
cli: cli,
controllerID: controllerID,
imageManager: &image{
@ -99,9 +95,6 @@ func NewProvider(ctx context.Context, cfg *config.Provider, pool *config.Pool, c
type LXD struct {
// cfg is the provider config for this provider.
cfg *config.Provider
// pool holds the config for the pool this provider is
// responsible for.
pool *config.Pool
// ctx is the context.
ctx context.Context
// cli is the LXD client.
@ -112,7 +105,7 @@ type LXD struct {
controllerID string
}
func (l *LXD) getProfiles(runner config.Runner) ([]string, error) {
func (l *LXD) getProfiles(flavor string) ([]string, error) {
ret := []string{}
if l.cfg.LXD.IncludeDefaultProfile {
ret = append(ret, "default")
@ -128,45 +121,14 @@ func (l *LXD) getProfiles(runner config.Runner) ([]string, error) {
set[profile] = struct{}{}
}
if _, ok := set[runner.Flavor]; !ok {
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "looking for profile %s", runner.Flavor)
if _, ok := set[flavor]; !ok {
return nil, errors.Wrapf(runnerErrors.ErrNotFound, "looking for profile %s", flavor)
}
ret = append(ret, runner.Flavor)
ret = append(ret, flavor)
return ret, nil
}
func (l *LXD) getCloudConfig(runner config.Runner, bootstrapParams params.BootstrapInstance, tools github.RunnerApplicationDownload, runnerName string) (string, error) {
cloudCfg := cloudconfig.NewDefaultCloudInitConfig()
installRunnerParams := cloudconfig.InstallRunnerParams{
FileName: *tools.Filename,
DownloadURL: *tools.DownloadURL,
GithubToken: bootstrapParams.GithubRunnerAccessToken,
RunnerUsername: config.DefaultUser,
RunnerGroup: config.DefaultUser,
RepoURL: bootstrapParams.RepoURL,
RunnerName: runnerName,
RunnerLabels: strings.Join(runner.Labels, ","),
}
installScript, err := cloudconfig.InstallRunnerScript(installRunnerParams)
if err != nil {
return "", errors.Wrap(err, "generating script")
}
cloudCfg.AddSSHKey(bootstrapParams.SSHKeys...)
cloudCfg.AddFile(installScript, "/install_runner.sh", "root:root", "755")
cloudCfg.AddRunCmd("/install_runner.sh")
cloudCfg.AddRunCmd("rm -f /install_runner.sh")
asStr, err := cloudCfg.Serialize()
if err != nil {
return "", errors.Wrap(err, "creating cloud config")
}
return asStr, nil
}
func (l *LXD) getTools(image *api.Image, tools []*github.RunnerApplicationDownload) (github.RunnerApplicationDownload, error) {
if image == nil {
return github.RunnerApplicationDownload{}, fmt.Errorf("nil image received")
@ -211,17 +173,6 @@ func (l *LXD) getTools(image *api.Image, tools []*github.RunnerApplicationDownlo
return github.RunnerApplicationDownload{}, fmt.Errorf("failed to find tools for OS %s and arch %s", osType, image.Architecture)
}
func (l *LXD) resolveArchitecture(runner config.Runner) (string, error) {
if string(runner.OSArch) == "" {
return configToLXDArchMap[config.Amd64], nil
}
arch, ok := configToLXDArchMap[runner.OSArch]
if !ok {
return "", fmt.Errorf("architecture %s is not supported", runner.OSArch)
}
return arch, nil
}
// sadly, the security.secureboot flag is a string encoded boolean.
func (l *LXD) secureBootEnabled() string {
if l.cfg.LXD.SecureBoot {
@ -232,23 +183,18 @@ func (l *LXD) secureBootEnabled() string {
func (l *LXD) getCreateInstanceArgs(bootstrapParams params.BootstrapInstance) (api.InstancesPost, error) {
name := fmt.Sprintf("runner-manager-%s", uuid.New())
runner, err := util.FindRunnerType(bootstrapParams.RunnerType, l.pool.Runners)
if err != nil {
return api.InstancesPost{}, errors.Wrap(err, "fetching runner")
}
profiles, err := l.getProfiles(runner)
profiles, err := l.getProfiles(bootstrapParams.Flavor)
if err != nil {
return api.InstancesPost{}, errors.Wrap(err, "fetching profiles")
}
arch, err := l.resolveArchitecture(runner)
arch, err := resolveArchitecture(bootstrapParams.OSArch)
if err != nil {
return api.InstancesPost{}, errors.Wrap(err, "fetching archictecture")
}
image, err := l.imageManager.EnsureImage(runner.Image, config.LXDImageVirtualMachine, arch)
image, err := l.imageManager.EnsureImage(bootstrapParams.Image, config.LXDImageVirtualMachine, arch)
if err != nil {
return api.InstancesPost{}, errors.Wrap(err, "getting image details")
}
@ -258,7 +204,7 @@ func (l *LXD) getCreateInstanceArgs(bootstrapParams params.BootstrapInstance) (a
return api.InstancesPost{}, errors.Wrap(err, "getting tools")
}
cloudCfg, err := l.getCloudConfig(runner, bootstrapParams, tools, name)
cloudCfg, err := util.GetCloudConfig(bootstrapParams, tools, name)
if err != nil {
return api.InstancesPost{}, errors.Wrap(err, "generating cloud-config")
}

View file

@ -2,6 +2,7 @@ package lxd
import (
"context"
"fmt"
"io/ioutil"
"log"
"runner-manager/config"
@ -41,8 +42,14 @@ func lxdInstanceToAPIInstance(instance *api.InstanceFull) params.Instance {
}
}
}
instanceArch, ok := lxdToConfigArch[instance.Architecture]
if !ok {
log.Printf("failed to find OS architecture")
}
return params.Instance{
OSArch: instance.Architecture,
OSArch: instanceArch,
ProviderID: instance.Name,
Name: instance.Name,
OSType: osType,
@ -103,3 +110,14 @@ func projectName(cfg config.LXD) string {
}
return DefaultProjectName
}
func resolveArchitecture(osArch config.OSArch) (string, error) {
if string(osArch) == "" {
return configToLXDArchMap[config.Amd64], nil
}
arch, ok := configToLXDArchMap[osArch]
if !ok {
return "", fmt.Errorf("architecture %s is not supported", osArch)
}
return arch, nil
}

View file

@ -0,0 +1,27 @@
package providers
import (
"context"
"runner-manager/config"
"runner-manager/runner/common"
"runner-manager/runner/providers/lxd"
"github.com/pkg/errors"
)
// LoadProvidersFromConfig loads all providers from the config and populates
// a map with them.
func LoadProvidersFromConfig(ctx context.Context, cfg config.Config, controllerID string) (map[string]common.Provider, error) {
providers := map[string]common.Provider{}
for _, providerCfg := range cfg.Providers {
switch providerCfg.ProviderType {
case config.LXDProvider:
provider, err := lxd.NewProvider(ctx, &providerCfg, controllerID)
if err != nil {
return nil, errors.Wrap(err, "creating provider")
}
providers[providerCfg.Name] = provider
}
}
return providers, nil
}

View file

@ -2,11 +2,14 @@ package runner
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runner-manager/config"
gErrors "runner-manager/errors"
"runner-manager/runner/common"
"runner-manager/runner/providers"
"runner-manager/util"
"sync"
@ -15,10 +18,22 @@ import (
"golang.org/x/crypto/ssh"
)
func NewRunner(ctx context.Context, cfg *config.Config) (*Runner, error) {
func NewRunner(ctx context.Context, cfg config.Config) (*Runner, error) {
ghc, err := util.GithubClientFromConfig(ctx, cfg.Github)
if err != nil {
return nil, errors.Wrap(err, "getting github client")
}
providers, err := providers.LoadProvidersFromConfig(ctx, cfg, "")
if err != nil {
return nil, errors.Wrap(err, "loading providers")
}
runner := &Runner{
ctx: ctx,
config: cfg,
ctx: ctx,
config: cfg,
ghc: ghc,
providers: providers,
}
if err := runner.ensureSSHKeys(); err != nil {
@ -34,8 +49,35 @@ type Runner struct {
ctx context.Context
ghc *github.Client
config *config.Config
pools []common.PoolManager
controllerID string
config config.Config
repositories map[string]common.PoolManager
organizations map[string]common.PoolManager
providers map[string]common.Provider
}
func (r *Runner) getRepoSecret(repoName string) (string, error) {
return "", nil
}
func (r *Runner) getOrgSecret(orgName string) (string, error) {
return "", nil
}
func (r *Runner) ValidateHookBody(hookTargetType, signature, entity string, body []byte) error {
var secret string
var err error
switch hookTargetType {
case "repository":
secret, err = r.getRepoSecret(entity)
case "organization":
secret, err = r.getOrgSecret(entity)
default:
return gErrors.NewBadRequestError("invalid hook type: %s", hookTargetType)
}
fmt.Println(secret, err)
return nil
}
func (r *Runner) sshDir() string {