145 lines
3.5 KiB
Go
145 lines
3.5 KiB
Go
package runner
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
actions_module "code.gitea.io/gitea/models/actions"
|
|
docker_module "code.gitea.io/gitea/modules/docker"
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
)
|
|
|
|
func RegistGlobalRunner(ctx context.Context) error {
|
|
log.Info("获取全局RunnerToken...")
|
|
actionRunnerToken, err := actions_module.NewRunnerToken(ctx, 0, 0)
|
|
if err != nil {
|
|
return fmt.Errorf("获取全局RunnerToken失败:%v", err)
|
|
}
|
|
runnerCount := setting.Runner.Count
|
|
for i := 0; i < runnerCount; i++ {
|
|
err := RegistRunner(ctx, actionRunnerToken.Token)
|
|
if err != nil {
|
|
return fmt.Errorf("注册Runner失败:%v", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func RegistRunner(ctx context.Context, token string) error {
|
|
log.Info("开始注册Runner...")
|
|
cli, err := docker_module.CreateDockerClient(&ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("Docker client创建失败:%v", err)
|
|
}
|
|
log.Info("[RegistRunner]Docker client创建成功")
|
|
defer cli.Close()
|
|
//拉取act_runner镜像
|
|
dockerHost, err := docker_module.GetDockerSocketPath()
|
|
if err != nil {
|
|
return fmt.Errorf("获取docker socket路径失败:%v", err)
|
|
}
|
|
// 拉取镜像
|
|
err = docker_module.PullImageSync(cli, dockerHost, setting.Runner.Image)
|
|
if err != nil {
|
|
return fmt.Errorf("拉取act_runner镜像失败:%v", err)
|
|
}
|
|
//获取本机IP
|
|
ips, err := getLocalIP()
|
|
if err != nil {
|
|
return fmt.Errorf("获取本机IP失败:%v", err)
|
|
}
|
|
//获取InstanceUrl
|
|
conntype := strings.Split(setting.AppURL, "://")[0]
|
|
port := setting.HTTPPort
|
|
instanceURL := conntype + "://" + ips[0] + ":" + port
|
|
timestamp := time.Now().Format("20060102150405")
|
|
//Runner配置
|
|
env := []string{
|
|
"GITEA_INSTANCE_URL=" + instanceURL,
|
|
"GITEA_RUNNER_REGISTRATION_TOKEN=" + token,
|
|
"GITEA_RUNNER_NAME=runner-" + timestamp,
|
|
}
|
|
binds := []string{
|
|
"/var/run/docker.sock:/var/run/docker.sock",
|
|
}
|
|
containerName := "runner-" + timestamp
|
|
//创建并启动Runner容器
|
|
opts := &docker_module.CreateDevcontainerOptions{
|
|
Name: containerName,
|
|
Image: setting.Runner.Image,
|
|
Binds: binds,
|
|
ContainerEnv: env,
|
|
}
|
|
err = docker_module.CreateAndStartContainer(cli, opts)
|
|
if err != nil {
|
|
return fmt.Errorf("创建并注册Runner失败:%v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func DeleteRunnerByName(ctx context.Context, runnerName string) error {
|
|
log.Info("开始停止并删除容器: %s", runnerName)
|
|
|
|
// 创建Docker客户端
|
|
cli, err := docker_module.CreateDockerClient(&ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("Docker client创建失败:%v", err)
|
|
}
|
|
log.Info("[StopAndRemoveContainer]Docker client创建成功")
|
|
defer cli.Close()
|
|
err = docker_module.DeleteContainer(cli, runnerName)
|
|
if err != nil {
|
|
return fmt.Errorf("Runner创建失败:%v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getLocalIP() ([]string, error) {
|
|
var ips []string
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, iface := range interfaces {
|
|
if iface.Flags&net.FlagUp == 0 ||
|
|
iface.Flags&net.FlagLoopback != 0 {
|
|
continue
|
|
}
|
|
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
// 遍历地址列表
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
ip = v.IP
|
|
case *net.IPAddr:
|
|
ip = v.IP
|
|
}
|
|
if ip == nil || ip.IsLoopback() {
|
|
continue
|
|
}
|
|
|
|
ip = ip.To4()
|
|
if ip == nil {
|
|
continue // 非IPv4地址
|
|
}
|
|
|
|
ips = append(ips, ip.String())
|
|
}
|
|
}
|
|
if len(ips) == 0 {
|
|
return nil, fmt.Errorf("no valid IP address found")
|
|
}
|
|
return ips, nil
|
|
}
|