mirror of
https://github.com/datarhei/core.git
synced 2025-10-05 07:57:13 +08:00
356 lines
6.6 KiB
Go
356 lines
6.6 KiB
Go
package forwarder
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
apiclient "github.com/datarhei/core/v16/cluster/client"
|
|
iamaccess "github.com/datarhei/core/v16/iam/access"
|
|
iamidentity "github.com/datarhei/core/v16/iam/identity"
|
|
"github.com/datarhei/core/v16/log"
|
|
"github.com/datarhei/core/v16/restream/app"
|
|
)
|
|
|
|
// Forwarder forwards any HTTP request from a follower to the leader
|
|
type Forwarder interface {
|
|
SetLeader(address string)
|
|
HasLeader() bool
|
|
|
|
Join(origin, id, raftAddress, peerAddress string) error
|
|
Leave(origin, id string) error
|
|
Snapshot(origin string) (io.ReadCloser, error)
|
|
|
|
AddProcess(origin string, config *app.Config) error
|
|
UpdateProcess(origin string, id app.ProcessID, config *app.Config) error
|
|
RemoveProcess(origin string, id app.ProcessID) error
|
|
SetProcessCommand(origin string, id app.ProcessID, command string) error
|
|
SetProcessMetadata(origin string, id app.ProcessID, key string, data interface{}) error
|
|
|
|
AddIdentity(origin string, identity iamidentity.User) error
|
|
UpdateIdentity(origin, name string, identity iamidentity.User) error
|
|
SetPolicies(origin, name string, policies []iamaccess.Policy) error
|
|
RemoveIdentity(origin string, name string) error
|
|
|
|
CreateLock(origin string, name string, validUntil time.Time) error
|
|
DeleteLock(origin string, name string) error
|
|
|
|
SetKV(origin, key, value string) error
|
|
UnsetKV(origin, key string) error
|
|
|
|
IsReady(origin string) error
|
|
}
|
|
|
|
type forwarder struct {
|
|
id string
|
|
lock sync.RWMutex
|
|
|
|
client apiclient.APIClient
|
|
|
|
logger log.Logger
|
|
}
|
|
|
|
type ForwarderConfig struct {
|
|
ID string
|
|
Logger log.Logger
|
|
}
|
|
|
|
func New(config ForwarderConfig) (Forwarder, error) {
|
|
f := &forwarder{
|
|
id: config.ID,
|
|
logger: config.Logger,
|
|
}
|
|
|
|
if f.logger == nil {
|
|
f.logger = log.New("")
|
|
}
|
|
|
|
tr := &http.Transport{
|
|
MaxIdleConns: 10,
|
|
IdleConnTimeout: 30 * time.Second,
|
|
}
|
|
|
|
client := &http.Client{
|
|
Transport: tr,
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
|
|
f.client = apiclient.APIClient{
|
|
Client: client,
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func (f *forwarder) SetLeader(address string) {
|
|
f.lock.Lock()
|
|
defer f.lock.Unlock()
|
|
|
|
if f.client.Address == address {
|
|
return
|
|
}
|
|
|
|
f.logger.Debug().Log("Setting leader address to %s", address)
|
|
|
|
f.client.Address = address
|
|
}
|
|
|
|
func (f *forwarder) HasLeader() bool {
|
|
return len(f.client.Address) != 0
|
|
}
|
|
|
|
func (f *forwarder) Join(origin, id, raftAddress, peerAddress string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.JoinRequest{
|
|
ID: id,
|
|
RaftAddress: raftAddress,
|
|
}
|
|
|
|
f.logger.Debug().WithField("request", r).Log("Forwarding to leader")
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
if len(peerAddress) != 0 {
|
|
client = apiclient.APIClient{
|
|
Address: peerAddress,
|
|
Client: f.client.Client,
|
|
}
|
|
}
|
|
|
|
return client.Join(origin, r)
|
|
}
|
|
|
|
func (f *forwarder) Leave(origin, id string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.logger.Debug().WithField("id", id).Log("Forwarding to leader")
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.Leave(origin, id)
|
|
}
|
|
|
|
func (f *forwarder) Snapshot(origin string) (io.ReadCloser, error) {
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.Snapshot(origin)
|
|
}
|
|
|
|
func (f *forwarder) AddProcess(origin string, config *app.Config) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.AddProcessRequest{
|
|
Config: *config,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.AddProcess(origin, r)
|
|
}
|
|
|
|
func (f *forwarder) UpdateProcess(origin string, id app.ProcessID, config *app.Config) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.UpdateProcessRequest{
|
|
Config: *config,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.UpdateProcess(origin, id, r)
|
|
}
|
|
|
|
func (f *forwarder) SetProcessCommand(origin string, id app.ProcessID, command string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.SetProcessCommandRequest{
|
|
Command: command,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.SetProcessCommand(origin, id, r)
|
|
}
|
|
|
|
func (f *forwarder) SetProcessMetadata(origin string, id app.ProcessID, key string, data interface{}) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.SetProcessMetadataRequest{
|
|
Metadata: data,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.SetProcessMetadata(origin, id, key, r)
|
|
}
|
|
|
|
func (f *forwarder) RemoveProcess(origin string, id app.ProcessID) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.RemoveProcess(origin, id)
|
|
}
|
|
|
|
func (f *forwarder) AddIdentity(origin string, identity iamidentity.User) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.AddIdentityRequest{
|
|
Identity: identity,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.AddIdentity(origin, r)
|
|
}
|
|
|
|
func (f *forwarder) UpdateIdentity(origin, name string, identity iamidentity.User) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.UpdateIdentityRequest{
|
|
Identity: identity,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.UpdateIdentity(origin, name, r)
|
|
}
|
|
|
|
func (f *forwarder) SetPolicies(origin, name string, policies []iamaccess.Policy) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.SetPoliciesRequest{
|
|
Policies: policies,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.SetPolicies(origin, name, r)
|
|
}
|
|
|
|
func (f *forwarder) RemoveIdentity(origin string, name string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.RemoveIdentity(origin, name)
|
|
}
|
|
|
|
func (f *forwarder) CreateLock(origin string, name string, validUntil time.Time) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.LockRequest{
|
|
Name: name,
|
|
ValidUntil: validUntil,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.Lock(origin, r)
|
|
}
|
|
|
|
func (f *forwarder) DeleteLock(origin string, name string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.Unlock(origin, name)
|
|
}
|
|
|
|
func (f *forwarder) SetKV(origin, key, value string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
r := apiclient.SetKVRequest{
|
|
Key: key,
|
|
Value: value,
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.SetKV(origin, r)
|
|
}
|
|
|
|
func (f *forwarder) UnsetKV(origin, key string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.UnsetKV(origin, key)
|
|
}
|
|
|
|
func (f *forwarder) IsReady(origin string) error {
|
|
if origin == "" {
|
|
origin = f.id
|
|
}
|
|
|
|
f.lock.RLock()
|
|
client := f.client
|
|
f.lock.RUnlock()
|
|
|
|
return client.IsReady(origin)
|
|
}
|