Handle org runners
This commit is contained in:
parent
bf0a5bf147
commit
ebec0dda52
18 changed files with 1028 additions and 184 deletions
|
|
@ -1 +0,0 @@
|
|||
package pool
|
||||
46
runner/pool/repository.go
Normal file
46
runner/pool/repository.go
Normal 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() {
|
||||
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
27
runner/providers/providers.go
Normal file
27
runner/providers/providers.go
Normal 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
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue