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
|
act_runner
|
||||||
.env
|
.env
|
||||||
|
.runner
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/core"
|
|
||||||
"gitea.com/gitea/proto-go/ping/v1/pingv1connect"
|
"gitea.com/gitea/proto-go/ping/v1/pingv1connect"
|
||||||
"gitea.com/gitea/proto-go/runner/v1/runnerv1connect"
|
"gitea.com/gitea/proto-go/runner/v1/runnerv1connect"
|
||||||
|
|
||||||
"github.com/bufbuild/connect-go"
|
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a new runner client.
|
// New returns a new runner client.
|
||||||
func New(endpoint, secret string, opts ...Option) *HTTPClient {
|
func New(endpoint string, opts ...Option) *HTTPClient {
|
||||||
cfg := &config{}
|
cfg := &config{}
|
||||||
|
|
||||||
// Loop through each option
|
// Loop through each option
|
||||||
|
@ -25,15 +22,6 @@ func New(endpoint, secret string, opts ...Option) *HTTPClient {
|
||||||
opt.apply(cfg)
|
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 {
|
if cfg.httpClient == nil {
|
||||||
cfg.httpClient = &http.Client{
|
cfg.httpClient = &http.Client{
|
||||||
Timeout: 1 * time.Minute,
|
Timeout: 1 * time.Minute,
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/core"
|
||||||
|
|
||||||
"github.com/bufbuild/connect-go"
|
"github.com/bufbuild/connect-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,3 +59,21 @@ func WithGRPCWeb(c bool) Option {
|
||||||
cfg.opts = append(cfg.opts, connect.WithGRPCWeb())
|
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/config"
|
||||||
"gitea.com/gitea/act_runner/engine"
|
"gitea.com/gitea/act_runner/engine"
|
||||||
"gitea.com/gitea/act_runner/poller"
|
"gitea.com/gitea/act_runner/poller"
|
||||||
|
"gitea.com/gitea/act_runner/register"
|
||||||
"gitea.com/gitea/act_runner/runtime"
|
"gitea.com/gitea/act_runner/runtime"
|
||||||
pingv1 "gitea.com/gitea/proto-go/ping/v1"
|
pingv1 "gitea.com/gitea/proto-go/ping/v1"
|
||||||
runnerv1 "gitea.com/gitea/proto-go/runner/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)
|
initLogging(cfg)
|
||||||
|
|
||||||
// try to connect to docker daemon
|
// initial http client
|
||||||
// if failed, exit with error
|
|
||||||
if err := engine.Start(ctx); err != nil {
|
|
||||||
log.WithError(err).Fatalln("failed to connect docker daemon engine")
|
|
||||||
}
|
|
||||||
|
|
||||||
cli := client.New(
|
cli := client.New(
|
||||||
cfg.Client.Address,
|
cfg.Client.Address,
|
||||||
cfg.Client.Secret,
|
|
||||||
client.WithSkipVerify(cfg.Client.SkipVerify),
|
client.WithSkipVerify(cfg.Client.SkipVerify),
|
||||||
client.WithGRPC(cfg.Client.GRPC),
|
client.WithGRPC(cfg.Client.GRPC),
|
||||||
client.WithGRPCWeb(cfg.Client.GRPCWeb),
|
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
|
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{
|
runner := &runtime.Runner{
|
||||||
Client: cli,
|
Client: cli,
|
||||||
Machine: cfg.Runner.Name,
|
Machine: cfg.Runner.Name,
|
||||||
|
@ -80,11 +109,6 @@ func runDaemon(ctx context.Context, task *runtime.Task) func(cmd *cobra.Command,
|
||||||
poller := poller.New(
|
poller := poller.New(
|
||||||
cli,
|
cli,
|
||||||
runner.Run,
|
runner.Run,
|
||||||
&client.Filter{
|
|
||||||
OS: cfg.Platform.OS,
|
|
||||||
Arch: cfg.Platform.Arch,
|
|
||||||
Labels: cfg.Runner.Labels,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
g.Go(func() error {
|
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),
|
Args: cobra.MaximumNArgs(1),
|
||||||
RunE: runDaemon(ctx, task),
|
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
|
// add all command
|
||||||
rootCmd.AddCommand(daemonCmd, registerCmd)
|
rootCmd.AddCommand(daemonCmd)
|
||||||
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -27,13 +27,13 @@ type (
|
||||||
Address string `ignored:"true"`
|
Address string `ignored:"true"`
|
||||||
Proto string `envconfig:"GITEA_RPC_PROTO" default:"http"`
|
Proto string `envconfig:"GITEA_RPC_PROTO" default:"http"`
|
||||||
Host string `envconfig:"GITEA_RPC_HOST"`
|
Host string `envconfig:"GITEA_RPC_HOST"`
|
||||||
Secret string `envconfig:"GITEA_RPC_SECRET"`
|
|
||||||
SkipVerify bool `envconfig:"GITEA_RPC_SKIP_VERIFY"`
|
SkipVerify bool `envconfig:"GITEA_RPC_SKIP_VERIFY"`
|
||||||
GRPC bool `envconfig:"GITEA_RPC_GRPC" default:"true"`
|
GRPC bool `envconfig:"GITEA_RPC_GRPC" default:"true"`
|
||||||
GRPCWeb bool `envconfig:"GITEA_RPC_GRPC_WEB"`
|
GRPCWeb bool `envconfig:"GITEA_RPC_GRPC_WEB"`
|
||||||
}
|
}
|
||||||
|
|
||||||
Runner struct {
|
Runner struct {
|
||||||
|
UUID string `ignored:"true"`
|
||||||
Name string `envconfig:"GITEA_RUNNER_NAME"`
|
Name string `envconfig:"GITEA_RUNNER_NAME"`
|
||||||
Token string `envconfig:"GITEA_RUNNER_TOKEN" required:"true"`
|
Token string `envconfig:"GITEA_RUNNER_TOKEN" required:"true"`
|
||||||
Capacity int `envconfig:"GITEA_RUNNER_CAPACITY" default:"1"`
|
Capacity int `envconfig:"GITEA_RUNNER_CAPACITY" default:"1"`
|
||||||
|
@ -66,7 +66,7 @@ func FromEnviron() (Config, error) {
|
||||||
return cfg, err
|
return cfg, err
|
||||||
}
|
}
|
||||||
if runner.UUID != "" {
|
if runner.UUID != "" {
|
||||||
cfg.Client.Secret = runner.UUID
|
cfg.Runner.UUID = runner.UUID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,12 @@ package poller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/client"
|
"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"
|
runnerv1 "gitea.com/gitea/proto-go/runner/v1"
|
||||||
|
|
||||||
"github.com/appleboy/com/file"
|
|
||||||
"github.com/bufbuild/connect-go"
|
"github.com/bufbuild/connect-go"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -27,10 +22,9 @@ var (
|
||||||
defaultLabels = []string{"self-hosted"}
|
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{
|
return &Poller{
|
||||||
Client: cli,
|
Client: cli,
|
||||||
Filter: filter,
|
|
||||||
Dispatch: dispatch,
|
Dispatch: dispatch,
|
||||||
routineGroup: newRoutineGroup(),
|
routineGroup: newRoutineGroup(),
|
||||||
}
|
}
|
||||||
|
@ -45,41 +39,6 @@ type Poller struct {
|
||||||
errorRetryCounter int
|
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 {
|
func (p *Poller) Poll(ctx context.Context, n int) error {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
func(i int) {
|
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