2024-08-22 17:02:33 +02:00
|
|
|
package agent
|
2024-08-21 20:48:02 +02:00
|
|
|
|
2024-08-23 18:05:05 +02:00
|
|
|
import (
|
2024-08-23 18:31:02 +02:00
|
|
|
"github.com/openziti/zrok/agent/agentGrpc"
|
2024-09-16 19:12:12 +02:00
|
|
|
"github.com/openziti/zrok/agent/proctree"
|
2024-08-23 18:05:05 +02:00
|
|
|
"github.com/openziti/zrok/environment/env_core"
|
2024-09-24 20:52:20 +02:00
|
|
|
"github.com/openziti/zrok/sdk/golang/sdk"
|
2024-08-23 18:05:05 +02:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
"net"
|
2024-08-23 18:35:19 +02:00
|
|
|
"os"
|
2024-08-23 18:05:05 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type Agent struct {
|
2024-08-23 18:35:19 +02:00
|
|
|
root env_core.Root
|
|
|
|
agentSocket string
|
|
|
|
shares map[string]*share
|
2024-09-25 17:06:06 +02:00
|
|
|
addShare chan *share
|
|
|
|
rmShare chan *share
|
2024-08-23 18:35:19 +02:00
|
|
|
accesses map[string]*access
|
2024-09-25 17:06:06 +02:00
|
|
|
addAccess chan *access
|
|
|
|
rmAccess chan *access
|
2024-08-21 20:48:02 +02:00
|
|
|
}
|
|
|
|
|
2024-08-23 18:05:05 +02:00
|
|
|
func NewAgent(root env_core.Root) (*Agent, error) {
|
|
|
|
if !root.IsEnabled() {
|
|
|
|
return nil, errors.Errorf("unable to load environment; did you 'zrok enable'?")
|
|
|
|
}
|
|
|
|
return &Agent{
|
2024-09-25 17:06:06 +02:00
|
|
|
root: root,
|
|
|
|
shares: make(map[string]*share),
|
|
|
|
addShare: make(chan *share),
|
|
|
|
rmShare: make(chan *share),
|
|
|
|
accesses: make(map[string]*access),
|
|
|
|
addAccess: make(chan *access),
|
|
|
|
rmAccess: make(chan *access),
|
2024-08-23 18:05:05 +02:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Agent) Run() error {
|
|
|
|
logrus.Infof("started")
|
2024-08-23 18:35:19 +02:00
|
|
|
|
2024-09-16 19:39:27 +02:00
|
|
|
if err := proctree.Init("zrok Agent"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-09-13 20:39:30 +02:00
|
|
|
go a.manager()
|
|
|
|
|
2024-08-23 18:05:05 +02:00
|
|
|
agentSocket, err := a.root.AgentSocket()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
l, err := net.Listen("unix", agentSocket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-08-23 18:35:19 +02:00
|
|
|
a.agentSocket = agentSocket
|
|
|
|
|
2024-08-23 18:05:05 +02:00
|
|
|
srv := grpc.NewServer()
|
2024-09-25 17:06:06 +02:00
|
|
|
agentGrpc.RegisterAgentServer(srv, &agentGrpcImpl{agent: a})
|
2024-08-23 18:05:05 +02:00
|
|
|
if err := srv.Serve(l); err != nil {
|
|
|
|
return err
|
2024-08-21 20:48:02 +02:00
|
|
|
}
|
2024-08-23 18:35:19 +02:00
|
|
|
|
2024-08-23 18:05:05 +02:00
|
|
|
return nil
|
2024-08-21 20:48:02 +02:00
|
|
|
}
|
2024-08-23 18:35:19 +02:00
|
|
|
|
|
|
|
func (a *Agent) Shutdown() {
|
2024-09-16 19:12:12 +02:00
|
|
|
logrus.Infof("stopping")
|
|
|
|
|
2024-08-23 18:35:19 +02:00
|
|
|
if err := os.Remove(a.agentSocket); err != nil {
|
|
|
|
logrus.Warnf("unable to remove agent socket: %v", err)
|
|
|
|
}
|
2024-09-16 19:12:12 +02:00
|
|
|
for _, shr := range a.shares {
|
2024-09-16 19:19:12 +02:00
|
|
|
logrus.Debugf("stopping share '%v'", shr.token)
|
2024-09-25 17:06:06 +02:00
|
|
|
a.rmShare <- shr
|
2024-09-16 19:12:12 +02:00
|
|
|
}
|
|
|
|
for _, acc := range a.accesses {
|
2024-09-16 19:19:12 +02:00
|
|
|
logrus.Debugf("stopping access '%v'", acc.token)
|
2024-09-25 17:06:06 +02:00
|
|
|
a.rmAccess <- acc
|
2024-09-16 19:12:12 +02:00
|
|
|
}
|
2024-08-23 18:35:19 +02:00
|
|
|
}
|
2024-09-13 20:39:30 +02:00
|
|
|
|
|
|
|
func (a *Agent) manager() {
|
|
|
|
logrus.Info("started")
|
|
|
|
defer logrus.Warn("exited")
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
2024-09-25 17:06:06 +02:00
|
|
|
case inShare := <-a.addShare:
|
2024-09-13 20:39:30 +02:00
|
|
|
logrus.Infof("adding new share '%v'", inShare.token)
|
|
|
|
a.shares[inShare.token] = inShare
|
|
|
|
|
2024-09-25 17:06:06 +02:00
|
|
|
case outShare := <-a.rmShare:
|
2024-09-25 16:59:10 +02:00
|
|
|
if shr, found := a.shares[outShare.token]; found {
|
|
|
|
logrus.Infof("removing share '%v'", shr.token)
|
|
|
|
if err := proctree.StopChild(shr.process); err != nil {
|
|
|
|
logrus.Errorf("error stopping share '%v': %v", shr.token, err)
|
2024-09-16 19:12:12 +02:00
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
if err := proctree.WaitChild(shr.process); err != nil {
|
|
|
|
logrus.Errorf("error joining share '%v': %v", shr.token, err)
|
2024-09-16 19:12:12 +02:00
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
if !shr.reserved {
|
|
|
|
if err := a.deleteShare(shr.token); err != nil {
|
|
|
|
logrus.Errorf("error deleting share '%v': %v", shr.token, err)
|
2024-09-24 20:52:20 +02:00
|
|
|
}
|
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
delete(a.shares, shr.token)
|
2024-09-16 19:12:12 +02:00
|
|
|
} else {
|
|
|
|
logrus.Debug("skipping unidentified (orphaned) share removal")
|
|
|
|
}
|
2024-09-17 03:58:03 +02:00
|
|
|
|
2024-09-25 17:06:06 +02:00
|
|
|
case inAccess := <-a.addAccess:
|
2024-09-17 03:58:03 +02:00
|
|
|
logrus.Infof("adding new access '%v'", inAccess.frontendToken)
|
|
|
|
a.accesses[inAccess.frontendToken] = inAccess
|
|
|
|
|
2024-09-25 17:06:06 +02:00
|
|
|
case outAccess := <-a.rmAccess:
|
2024-09-25 16:59:10 +02:00
|
|
|
if acc, found := a.accesses[outAccess.frontendToken]; found {
|
|
|
|
logrus.Infof("removing access '%v'", acc.frontendToken)
|
|
|
|
if err := proctree.StopChild(acc.process); err != nil {
|
|
|
|
logrus.Errorf("error stopping access '%v': %v", acc.frontendToken, err)
|
2024-09-17 03:58:03 +02:00
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
if err := proctree.WaitChild(acc.process); err != nil {
|
|
|
|
logrus.Errorf("error joining access '%v': %v", acc.frontendToken, err)
|
2024-09-17 03:58:03 +02:00
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
if err := a.deleteAccess(acc.token, acc.frontendToken); err != nil {
|
|
|
|
logrus.Errorf("error deleting access '%v': %v", acc.frontendToken, err)
|
2024-09-24 20:52:20 +02:00
|
|
|
}
|
2024-09-25 16:59:10 +02:00
|
|
|
delete(a.accesses, acc.frontendToken)
|
2024-09-17 03:58:03 +02:00
|
|
|
} else {
|
|
|
|
logrus.Debug("skipping unidentified (orphaned) access removal")
|
|
|
|
}
|
2024-09-13 20:39:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-09-17 03:32:17 +02:00
|
|
|
|
2024-09-24 20:52:20 +02:00
|
|
|
func (a *Agent) deleteShare(token string) error {
|
2024-09-25 16:59:10 +02:00
|
|
|
logrus.Debugf("deleting share '%v'", token)
|
2024-09-24 20:52:20 +02:00
|
|
|
if err := sdk.DeleteShare(a.root, &sdk.Share{Token: token}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Agent) deleteAccess(token, frontendToken string) error {
|
2024-09-25 16:59:10 +02:00
|
|
|
logrus.Debugf("deleting access '%v'", frontendToken)
|
2024-09-24 20:52:20 +02:00
|
|
|
if err := sdk.DeleteAccess(a.root, &sdk.Access{Token: frontendToken, ShareToken: token}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-17 03:32:17 +02:00
|
|
|
type agentGrpcImpl struct {
|
|
|
|
agentGrpc.UnimplementedAgentServer
|
2024-09-25 17:06:06 +02:00
|
|
|
agent *Agent
|
2024-09-17 03:32:17 +02:00
|
|
|
}
|