mirror of
https://code.forgejo.org/forgejo/runner.git
synced 2024-11-21 20:27:17 +03:00
chore(runner): remove client secret and add UUID in runner
Signed-off-by: Bo-Yi.Wu <appleboy.tw@gmail.com>
This commit is contained in:
parent
bf5e3dc302
commit
e08495af09
9 changed files with 122 additions and 167 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
act_runner
|
||||
.env
|
||||
.runner
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gitea.com/gitea/act_runner/core"
|
||||
"gitea.com/gitea/proto-go/ping/v1/pingv1connect"
|
||||
"gitea.com/gitea/proto-go/runner/v1/runnerv1connect"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
// New returns a new runner client.
|
||||
func New(endpoint, secret string, opts ...Option) *HTTPClient {
|
||||
func New(endpoint string, opts ...Option) *HTTPClient {
|
||||
cfg := &config{}
|
||||
|
||||
// Loop through each option
|
||||
|
@ -25,15 +22,6 @@ func New(endpoint, secret string, opts ...Option) *HTTPClient {
|
|||
opt.apply(cfg)
|
||||
}
|
||||
|
||||
interceptor := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
|
||||
req.Header().Set(core.UUIDHeader, secret)
|
||||
return next(ctx, req)
|
||||
}
|
||||
})
|
||||
|
||||
cfg.opts = append(cfg.opts, connect.WithInterceptors(interceptor))
|
||||
|
||||
if cfg.httpClient == nil {
|
||||
cfg.httpClient = &http.Client{
|
||||
Timeout: 1 * time.Minute,
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"gitea.com/gitea/act_runner/core"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
)
|
||||
|
||||
|
@ -56,3 +59,21 @@ func WithGRPCWeb(c bool) Option {
|
|||
cfg.opts = append(cfg.opts, connect.WithGRPCWeb())
|
||||
})
|
||||
}
|
||||
|
||||
// WithUUIDHeader add runner uuid in header
|
||||
func WithUUIDHeader(uuid string) Option {
|
||||
return OptionFunc(func(cfg *config) {
|
||||
if uuid == "" {
|
||||
return
|
||||
}
|
||||
cfg.opts = append(
|
||||
cfg.opts,
|
||||
connect.WithInterceptors(connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
|
||||
req.Header().Set(core.UUIDHeader, uuid)
|
||||
return next(ctx, req)
|
||||
}
|
||||
})),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"gitea.com/gitea/act_runner/config"
|
||||
"gitea.com/gitea/act_runner/engine"
|
||||
"gitea.com/gitea/act_runner/poller"
|
||||
"gitea.com/gitea/act_runner/register"
|
||||
"gitea.com/gitea/act_runner/runtime"
|
||||
pingv1 "gitea.com/gitea/proto-go/ping/v1"
|
||||
runnerv1 "gitea.com/gitea/proto-go/runner/v1"
|
||||
|
@ -32,15 +33,9 @@ func runDaemon(ctx context.Context, task *runtime.Task) func(cmd *cobra.Command,
|
|||
|
||||
initLogging(cfg)
|
||||
|
||||
// try to connect to docker daemon
|
||||
// if failed, exit with error
|
||||
if err := engine.Start(ctx); err != nil {
|
||||
log.WithError(err).Fatalln("failed to connect docker daemon engine")
|
||||
}
|
||||
|
||||
// initial http client
|
||||
cli := client.New(
|
||||
cfg.Client.Address,
|
||||
cfg.Client.Secret,
|
||||
client.WithSkipVerify(cfg.Client.SkipVerify),
|
||||
client.WithGRPC(cfg.Client.GRPC),
|
||||
client.WithGRPCWeb(cfg.Client.GRPCWeb),
|
||||
|
@ -69,8 +64,42 @@ func runDaemon(ctx context.Context, task *runtime.Task) func(cmd *cobra.Command,
|
|||
}
|
||||
}
|
||||
|
||||
// register new runner
|
||||
if cfg.Runner.UUID == "" {
|
||||
register := register.New(
|
||||
cli,
|
||||
&client.Filter{
|
||||
OS: cfg.Platform.OS,
|
||||
Arch: cfg.Platform.Arch,
|
||||
Labels: cfg.Runner.Labels,
|
||||
},
|
||||
)
|
||||
|
||||
data, err := register.Register(ctx, cfg.Runner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data.UUID != "" {
|
||||
cfg.Runner.UUID = data.UUID
|
||||
}
|
||||
}
|
||||
|
||||
// try to connect to docker daemon
|
||||
// if failed, exit with error
|
||||
if err := engine.Start(ctx); err != nil {
|
||||
log.WithError(err).Fatalln("failed to connect docker daemon engine")
|
||||
}
|
||||
|
||||
var g errgroup.Group
|
||||
|
||||
cli = client.New(
|
||||
cfg.Client.Address,
|
||||
client.WithSkipVerify(cfg.Client.SkipVerify),
|
||||
client.WithGRPC(cfg.Client.GRPC),
|
||||
client.WithGRPCWeb(cfg.Client.GRPCWeb),
|
||||
client.WithUUIDHeader(cfg.Runner.UUID),
|
||||
)
|
||||
|
||||
runner := &runtime.Runner{
|
||||
Client: cli,
|
||||
Machine: cfg.Runner.Name,
|
||||
|
@ -80,11 +109,6 @@ func runDaemon(ctx context.Context, task *runtime.Task) func(cmd *cobra.Command,
|
|||
poller := poller.New(
|
||||
cli,
|
||||
runner.Run,
|
||||
&client.Filter{
|
||||
OS: cfg.Platform.OS,
|
||||
Arch: cfg.Platform.Arch,
|
||||
Labels: cfg.Runner.Labels,
|
||||
},
|
||||
)
|
||||
|
||||
g.Go(func() error {
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gitea.com/gitea/act_runner/client"
|
||||
"gitea.com/gitea/act_runner/config"
|
||||
"gitea.com/gitea/act_runner/poller"
|
||||
"gitea.com/gitea/act_runner/runtime"
|
||||
pingv1 "gitea.com/gitea/proto-go/ping/v1"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
"github.com/joho/godotenv"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func runRegister(ctx context.Context, task *runtime.Task) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
log.Infoln("Starting runner daemon")
|
||||
|
||||
_ = godotenv.Load(task.Input.EnvFile)
|
||||
cfg, err := config.FromEnviron()
|
||||
if err != nil {
|
||||
log.WithError(err).
|
||||
Fatalln("invalid configuration")
|
||||
}
|
||||
|
||||
initLogging(cfg)
|
||||
|
||||
cli := client.New(
|
||||
cfg.Client.Address,
|
||||
cfg.Client.Secret,
|
||||
client.WithSkipVerify(cfg.Client.SkipVerify),
|
||||
client.WithGRPC(cfg.Client.GRPC),
|
||||
client.WithGRPCWeb(cfg.Client.GRPCWeb),
|
||||
)
|
||||
|
||||
for {
|
||||
_, err := cli.Ping(ctx, connect.NewRequest(&pingv1.PingRequest{
|
||||
Data: cfg.Runner.Name,
|
||||
}))
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.WithError(err).
|
||||
Errorln("cannot ping the remote server")
|
||||
// TODO: if ping failed, retry or exit
|
||||
time.Sleep(time.Second)
|
||||
} else {
|
||||
log.Infoln("successfully connected the remote server")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
runner := &runtime.Runner{
|
||||
Client: cli,
|
||||
Machine: cfg.Runner.Name,
|
||||
Environ: cfg.Runner.Environ,
|
||||
}
|
||||
|
||||
poller := poller.New(
|
||||
cli,
|
||||
runner.Run,
|
||||
&client.Filter{
|
||||
OS: cfg.Platform.OS,
|
||||
Arch: cfg.Platform.Arch,
|
||||
Labels: cfg.Runner.Labels,
|
||||
},
|
||||
)
|
||||
|
||||
// register new runner
|
||||
if err := poller.Register(ctx, cfg.Runner); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infoln("successfully registered new runner")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
11
cmd/root.go
11
cmd/root.go
|
@ -56,17 +56,8 @@ func Execute(ctx context.Context) {
|
|||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: runDaemon(ctx, task),
|
||||
}
|
||||
|
||||
// ./act_runner daemon
|
||||
registerCmd := &cobra.Command{
|
||||
Aliases: []string{"register"},
|
||||
Use: "register new runner",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: runRegister(ctx, task),
|
||||
}
|
||||
|
||||
// add all command
|
||||
rootCmd.AddCommand(daemonCmd, registerCmd)
|
||||
rootCmd.AddCommand(daemonCmd)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
|
|
|
@ -27,13 +27,13 @@ type (
|
|||
Address string `ignored:"true"`
|
||||
Proto string `envconfig:"GITEA_RPC_PROTO" default:"http"`
|
||||
Host string `envconfig:"GITEA_RPC_HOST"`
|
||||
Secret string `envconfig:"GITEA_RPC_SECRET"`
|
||||
SkipVerify bool `envconfig:"GITEA_RPC_SKIP_VERIFY"`
|
||||
GRPC bool `envconfig:"GITEA_RPC_GRPC" default:"true"`
|
||||
GRPCWeb bool `envconfig:"GITEA_RPC_GRPC_WEB"`
|
||||
}
|
||||
|
||||
Runner struct {
|
||||
UUID string `ignored:"true"`
|
||||
Name string `envconfig:"GITEA_RUNNER_NAME"`
|
||||
Token string `envconfig:"GITEA_RUNNER_TOKEN" required:"true"`
|
||||
Capacity int `envconfig:"GITEA_RUNNER_CAPACITY" default:"1"`
|
||||
|
@ -66,7 +66,7 @@ func FromEnviron() (Config, error) {
|
|||
return cfg, err
|
||||
}
|
||||
if runner.UUID != "" {
|
||||
cfg.Client.Secret = runner.UUID
|
||||
cfg.Runner.UUID = runner.UUID
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,17 +2,12 @@ package poller
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gitea.com/gitea/act_runner/client"
|
||||
"gitea.com/gitea/act_runner/config"
|
||||
"gitea.com/gitea/act_runner/core"
|
||||
runnerv1 "gitea.com/gitea/proto-go/runner/v1"
|
||||
|
||||
"github.com/appleboy/com/file"
|
||||
"github.com/bufbuild/connect-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -27,10 +22,9 @@ var (
|
|||
defaultLabels = []string{"self-hosted"}
|
||||
)
|
||||
|
||||
func New(cli client.Client, dispatch func(context.Context, *runnerv1.Task) error, filter *client.Filter) *Poller {
|
||||
func New(cli client.Client, dispatch func(context.Context, *runnerv1.Task) error) *Poller {
|
||||
return &Poller{
|
||||
Client: cli,
|
||||
Filter: filter,
|
||||
Dispatch: dispatch,
|
||||
routineGroup: newRoutineGroup(),
|
||||
}
|
||||
|
@ -45,41 +39,6 @@ type Poller struct {
|
|||
errorRetryCounter int
|
||||
}
|
||||
|
||||
func (p *Poller) Register(ctx context.Context, cfg config.Runner) error {
|
||||
// check .runner config exist
|
||||
if file.IsFile(cfg.File) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// register new runner.
|
||||
resp, err := p.Client.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
||||
Name: cfg.Name,
|
||||
Token: cfg.Token,
|
||||
AgentLabels: append(defaultLabels, []string{p.Filter.OS, p.Filter.Arch}...),
|
||||
CustomLabels: p.Filter.Labels,
|
||||
}))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("poller: cannot register new runner")
|
||||
return err
|
||||
}
|
||||
|
||||
data := &core.Runner{
|
||||
ID: resp.Msg.Runner.Id,
|
||||
UUID: resp.Msg.Runner.Uuid,
|
||||
Name: resp.Msg.Runner.Name,
|
||||
Token: resp.Msg.Runner.Token,
|
||||
}
|
||||
|
||||
file, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("poller: cannot marshal the json input")
|
||||
return err
|
||||
}
|
||||
|
||||
// store runner config in .runner file
|
||||
return os.WriteFile(cfg.File, file, 0o644)
|
||||
}
|
||||
|
||||
func (p *Poller) Poll(ctx context.Context, n int) error {
|
||||
for i := 0; i < n; i++ {
|
||||
func(i int) {
|
||||
|
|
59
register/register.go
Normal file
59
register/register.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package register
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"gitea.com/gitea/act_runner/client"
|
||||
"gitea.com/gitea/act_runner/config"
|
||||
"gitea.com/gitea/act_runner/core"
|
||||
runnerv1 "gitea.com/gitea/proto-go/runner/v1"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var defaultLabels = []string{"self-hosted"}
|
||||
|
||||
func New(cli client.Client, filter *client.Filter) *Register {
|
||||
return &Register{
|
||||
Client: cli,
|
||||
Filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
type Register struct {
|
||||
Client client.Client
|
||||
Filter *client.Filter
|
||||
}
|
||||
|
||||
func (p *Register) Register(ctx context.Context, cfg config.Runner) (*core.Runner, error) {
|
||||
// register new runner.
|
||||
resp, err := p.Client.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{
|
||||
Name: cfg.Name,
|
||||
Token: cfg.Token,
|
||||
AgentLabels: append(defaultLabels, []string{p.Filter.OS, p.Filter.Arch}...),
|
||||
CustomLabels: p.Filter.Labels,
|
||||
}))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("poller: cannot register new runner")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := &core.Runner{
|
||||
ID: resp.Msg.Runner.Id,
|
||||
UUID: resp.Msg.Runner.Uuid,
|
||||
Name: resp.Msg.Runner.Name,
|
||||
Token: resp.Msg.Runner.Token,
|
||||
}
|
||||
|
||||
file, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("poller: cannot marshal the json input")
|
||||
return data, err
|
||||
}
|
||||
|
||||
// store runner config in .runner file
|
||||
return data, os.WriteFile(cfg.File, file, 0o644)
|
||||
}
|
Loading…
Reference in a new issue