WIP: implemented Ping, implemented Set and Shutdown in agent, and added umask
This commit is contained in:
@@ -19,9 +19,12 @@ limitations under the License.
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
pb "gitea.suyono.dev/suyono/go-agent/proto"
|
||||
@@ -32,8 +35,12 @@ import (
|
||||
|
||||
type Option interface {
|
||||
SocketPath() string
|
||||
Expiry() string
|
||||
StopGraceTime() time.Duration
|
||||
Background() bool
|
||||
ExecArgs() []string
|
||||
ExecEnv() []string
|
||||
ExecLogPath() string
|
||||
Umask() int
|
||||
}
|
||||
|
||||
type Storage interface {
|
||||
@@ -42,6 +49,18 @@ type Storage interface {
|
||||
Shutdown() error
|
||||
}
|
||||
|
||||
type BgProcFlag int
|
||||
|
||||
const (
|
||||
child BgProcFlag = iota
|
||||
parent
|
||||
)
|
||||
|
||||
const (
|
||||
goAgentDaemonEnvFlag = "GO_AGENT_DAEMON"
|
||||
goAgentDaemonLogPath = "GO_AGENT_DAEMON_LOG"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
pb.UnimplementedAgentServer
|
||||
stor Storage
|
||||
@@ -77,6 +96,48 @@ func (s *server) Shutdown(context.Context, *emptypb.Empty) (*emptypb.Empty, erro
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func GetDaemonLogPath() (string, error) {
|
||||
// The child process of the main program should call this function and set up the logging infrastructure
|
||||
envVal, ok := os.LookupEnv(goAgentDaemonLogPath)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("programming issue: parent process did not set log path")
|
||||
}
|
||||
return envVal, nil
|
||||
}
|
||||
|
||||
func ExecBackground(opt Option) (BgProcFlag, error) {
|
||||
var (
|
||||
cmd *exec.Cmd
|
||||
ok bool
|
||||
envVal string
|
||||
)
|
||||
|
||||
args := opt.ExecArgs()
|
||||
envVal, ok = os.LookupEnv(goAgentDaemonEnvFlag)
|
||||
if !opt.Background() || len(args) == 0 || (envVal == "1" && ok) {
|
||||
return child, nil
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
cmd = exec.Command(args[0], args[1:]...)
|
||||
} else {
|
||||
cmd = exec.Command(args[0])
|
||||
}
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=1", goAgentDaemonEnvFlag))
|
||||
if opt.ExecLogPath() != "" {
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", goAgentDaemonLogPath, opt.ExecLogPath()))
|
||||
}
|
||||
cmd.Env = append(cmd.Env, opt.ExecEnv()...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, nil
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return parent, err
|
||||
}
|
||||
|
||||
return parent, nil
|
||||
}
|
||||
|
||||
func Serve(ctx context.Context, opt Option) error {
|
||||
var (
|
||||
l net.Listener
|
||||
@@ -85,18 +146,30 @@ func Serve(ctx context.Context, opt Option) error {
|
||||
ok bool
|
||||
sw *atomic.Bool
|
||||
cancel context.CancelFunc
|
||||
bgFlag BgProcFlag
|
||||
)
|
||||
socketPath := opt.SocketPath()
|
||||
os.Remove(socketPath)
|
||||
|
||||
if l, err = net.Listen("unix", socketPath); err != nil {
|
||||
return fmt.Errorf("failed to listen on unix socket: %w", err)
|
||||
if bgFlag, err = ExecBackground(opt); err != nil {
|
||||
return fmt.Errorf("could not start background process: %w", err)
|
||||
}
|
||||
if bgFlag == parent {
|
||||
return nil
|
||||
}
|
||||
|
||||
_ = os.Remove(opt.SocketPath())
|
||||
|
||||
oldUmask := unix.Umask(opt.Umask())
|
||||
if l, err = net.Listen("unix", opt.SocketPath()); err != nil {
|
||||
return fmt.Errorf("failed to listen on unix socket: %w", err)
|
||||
}
|
||||
unix.Umask(oldUmask)
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterAgentServer(grpcServer, &server{stor: storage.NewInMap()})
|
||||
errChan := make(chan error, 1)
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
pb.RegisterAgentServer(grpcServer, &server{
|
||||
stor: storage.NewInMap(cancel),
|
||||
})
|
||||
errChan := make(chan error, 1)
|
||||
sw = new(atomic.Bool)
|
||||
sw.Store(false)
|
||||
|
||||
@@ -137,3 +210,7 @@ fsl:
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *server) Ping(ctx context.Context, req *emptypb.Empty) (*emptypb.Empty, error) {
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user