mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-21 07:51:28 +02:00
refactor(agent): extract agent pool and HTTP utilities to dedicated package
Moved non-agent-specific logic from agent/pkg/agent/ to internal/agentpool/: - pool.go: Agent pool management (Get, Add, Remove, List, Iter, etc.) - http_requests.go: HTTP utilities (health checks, forwarding, websockets, reverse proxy) - agent.go: Agent struct with HTTP client management This separates general-purpose pool management from agent-specific configuration, improving code organization and making the agent package focused on agent config only.
This commit is contained in:
@@ -20,7 +20,6 @@ require (
|
|||||||
github.com/bytedance/sonic v1.14.2
|
github.com/bytedance/sonic v1.14.2
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/puzpuzpuz/xsync/v4 v4.2.0
|
|
||||||
github.com/rs/zerolog v1.34.0
|
github.com/rs/zerolog v1.34.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/valyala/fasthttp v1.68.0
|
github.com/valyala/fasthttp v1.68.0
|
||||||
@@ -94,6 +93,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
|
github.com/puzpuzpuz/xsync/v4 v4.2.0 // indirect
|
||||||
github.com/quic-go/qpack v0.6.0 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/quic-go/quic-go v0.58.0 // indirect
|
github.com/quic-go/quic-go v0.58.0 // indirect
|
||||||
github.com/samber/lo v1.52.0 // indirect
|
github.com/samber/lo v1.52.0 // indirect
|
||||||
@@ -107,6 +107,7 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.68.0 // indirect
|
||||||
github.com/vincent-petithory/dataurl v1.0.0 // indirect
|
github.com/vincent-petithory/dataurl v1.0.0 // indirect
|
||||||
github.com/yusing/ds v0.3.1 // indirect
|
github.com/yusing/ds v0.3.1 // indirect
|
||||||
github.com/yusing/gointernals v0.1.16 // indirect
|
github.com/yusing/gointernals v0.1.16 // indirect
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
package agent
|
|
||||||
|
|
||||||
import (
|
|
||||||
"iter"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
var agentPool = xsync.NewMap[string, *AgentConfig](xsync.WithPresize(10))
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if strings.HasSuffix(os.Args[0], ".test") {
|
|
||||||
agentPool.Store("test-agent", &AgentConfig{
|
|
||||||
Addr: "test-agent",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAgent(agentAddrOrDockerHost string) (*AgentConfig, bool) {
|
|
||||||
if !IsDockerHostAgent(agentAddrOrDockerHost) {
|
|
||||||
return getAgentByAddr(agentAddrOrDockerHost)
|
|
||||||
}
|
|
||||||
return getAgentByAddr(GetAgentAddrFromDockerHost(agentAddrOrDockerHost))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAgentByName(name string) (*AgentConfig, bool) {
|
|
||||||
for _, agent := range agentPool.Range {
|
|
||||||
if agent.Name == name {
|
|
||||||
return agent, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddAgent(agent *AgentConfig) {
|
|
||||||
agentPool.Store(agent.Addr, agent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveAgent(agent *AgentConfig) {
|
|
||||||
agentPool.Delete(agent.Addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveAllAgents() {
|
|
||||||
agentPool.Clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ListAgents() []*AgentConfig {
|
|
||||||
agents := make([]*AgentConfig, 0, agentPool.Size())
|
|
||||||
for _, agent := range agentPool.Range {
|
|
||||||
agents = append(agents, agent)
|
|
||||||
}
|
|
||||||
return agents
|
|
||||||
}
|
|
||||||
|
|
||||||
func IterAgents() iter.Seq2[string, *AgentConfig] {
|
|
||||||
return agentPool.Range
|
|
||||||
}
|
|
||||||
|
|
||||||
func NumAgents() int {
|
|
||||||
return agentPool.Size()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAgentByAddr(addr string) (agent *AgentConfig, ok bool) {
|
|
||||||
agent, ok = agentPool.Load(addr)
|
|
||||||
return agent, ok
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -15,8 +16,8 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/valyala/fasthttp"
|
|
||||||
"github.com/yusing/godoxy/agent/pkg/certs"
|
"github.com/yusing/godoxy/agent/pkg/certs"
|
||||||
|
httputils "github.com/yusing/goutils/http"
|
||||||
"github.com/yusing/goutils/version"
|
"github.com/yusing/goutils/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,10 +27,8 @@ type AgentConfig struct {
|
|||||||
Version version.Version `json:"version" swaggertype:"string"`
|
Version version.Version `json:"version" swaggertype:"string"`
|
||||||
Runtime ContainerRuntime `json:"runtime"`
|
Runtime ContainerRuntime `json:"runtime"`
|
||||||
|
|
||||||
httpClient *http.Client
|
tlsConfig tls.Config
|
||||||
fasthttpClientHealthCheck *fasthttp.Client
|
l zerolog.Logger
|
||||||
tlsConfig tls.Config
|
|
||||||
l zerolog.Logger
|
|
||||||
} // @name Agent
|
} // @name Agent
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -85,7 +84,8 @@ func (cfg *AgentConfig) Parse(addr string) error {
|
|||||||
|
|
||||||
var serverVersion = version.Get()
|
var serverVersion = version.Get()
|
||||||
|
|
||||||
func (cfg *AgentConfig) StartWithCerts(ctx context.Context, ca, crt, key []byte) error {
|
// InitWithCerts initializes the agent config with the given CA, certificate, and key.
|
||||||
|
func (cfg *AgentConfig) InitWithCerts(ctx context.Context, ca, crt, key []byte) error {
|
||||||
clientCert, err := tls.X509KeyPair(crt, key)
|
clientCert, err := tls.X509KeyPair(crt, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -104,12 +104,6 @@ func (cfg *AgentConfig) StartWithCerts(ctx context.Context, ca, crt, key []byte)
|
|||||||
ServerName: CertsDNSName,
|
ServerName: CertsDNSName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// create transport and http client
|
|
||||||
cfg.httpClient = cfg.NewHTTPClient()
|
|
||||||
applyNormalTransportConfig(cfg.httpClient)
|
|
||||||
|
|
||||||
cfg.fasthttpClientHealthCheck = cfg.NewFastHTTPHealthCheckClient()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -163,7 +157,8 @@ func (cfg *AgentConfig) StartWithCerts(ctx context.Context, ca, crt, key []byte)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AgentConfig) Start(ctx context.Context) error {
|
// Init initializes the agent config with the given context.
|
||||||
|
func (cfg *AgentConfig) Init(ctx context.Context) error {
|
||||||
filepath, ok := certs.AgentCertsFilepath(cfg.Addr)
|
filepath, ok := certs.AgentCertsFilepath(cfg.Addr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid agent host: %s", cfg.Addr)
|
return fmt.Errorf("invalid agent host: %s", cfg.Addr)
|
||||||
@@ -179,32 +174,7 @@ func (cfg *AgentConfig) Start(ctx context.Context) error {
|
|||||||
return fmt.Errorf("failed to extract agent certs: %w", err)
|
return fmt.Errorf("failed to extract agent certs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg.StartWithCerts(ctx, ca, crt, key)
|
return cfg.InitWithCerts(ctx, ca, crt, key)
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg *AgentConfig) NewHTTPClient() *http.Client {
|
|
||||||
return &http.Client{
|
|
||||||
Transport: cfg.Transport(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg *AgentConfig) NewFastHTTPHealthCheckClient() *fasthttp.Client {
|
|
||||||
return &fasthttp.Client{
|
|
||||||
Dial: func(addr string) (net.Conn, error) {
|
|
||||||
if addr != AgentHost+":443" {
|
|
||||||
return nil, &net.AddrError{Err: "invalid address", Addr: addr}
|
|
||||||
}
|
|
||||||
return net.Dial("tcp", cfg.Addr)
|
|
||||||
},
|
|
||||||
TLSConfig: &cfg.tlsConfig,
|
|
||||||
ReadTimeout: 5 * time.Second,
|
|
||||||
WriteTimeout: 3 * time.Second,
|
|
||||||
DisableHeaderNamesNormalizing: true,
|
|
||||||
DisablePathNormalizing: true,
|
|
||||||
NoDefaultUserAgentHeader: true,
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AgentConfig) Transport() *http.Transport {
|
func (cfg *AgentConfig) Transport() *http.Transport {
|
||||||
@@ -222,6 +192,10 @@ func (cfg *AgentConfig) Transport() *http.Transport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cfg *AgentConfig) TLSConfig() *tls.Config {
|
||||||
|
return &cfg.tlsConfig
|
||||||
|
}
|
||||||
|
|
||||||
var dialer = &net.Dialer{Timeout: 5 * time.Second}
|
var dialer = &net.Dialer{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
func (cfg *AgentConfig) DialContext(ctx context.Context) (net.Conn, error) {
|
func (cfg *AgentConfig) DialContext(ctx context.Context) (net.Conn, error) {
|
||||||
@@ -232,10 +206,29 @@ func (cfg *AgentConfig) String() string {
|
|||||||
return cfg.Name + "@" + cfg.Addr
|
return cfg.Name + "@" + cfg.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyNormalTransportConfig(client *http.Client) {
|
func (cfg *AgentConfig) do(ctx context.Context, method, endpoint string, body io.Reader) (*http.Response, error) {
|
||||||
transport := client.Transport.(*http.Transport)
|
req, err := http.NewRequestWithContext(ctx, method, APIBaseURL+endpoint, body)
|
||||||
transport.MaxIdleConns = 100
|
if err != nil {
|
||||||
transport.MaxIdleConnsPerHost = 100
|
return nil, err
|
||||||
transport.ReadBufferSize = 16384
|
}
|
||||||
transport.WriteBufferSize = 16384
|
client := http.Client{
|
||||||
|
Transport: cfg.Transport(),
|
||||||
|
}
|
||||||
|
return client.Do(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *AgentConfig) fetchString(ctx context.Context, endpoint string) (string, int, error) {
|
||||||
|
resp, err := cfg.do(ctx, "GET", endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, release, err := httputils.ReadAllBody(resp)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
ret := string(data)
|
||||||
|
release(data)
|
||||||
|
return ret, resp.StatusCode, nil
|
||||||
}
|
}
|
||||||
|
|||||||
54
internal/agentpool/agent.go
Normal file
54
internal/agentpool/agent.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package agentpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Agent struct {
|
||||||
|
*agent.AgentConfig
|
||||||
|
|
||||||
|
httpClient *http.Client
|
||||||
|
fasthttpHcClient *fasthttp.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAgent(cfg *agent.AgentConfig) *Agent {
|
||||||
|
transport := cfg.Transport()
|
||||||
|
transport.MaxIdleConns = 100
|
||||||
|
transport.MaxIdleConnsPerHost = 100
|
||||||
|
transport.ReadBufferSize = 16384
|
||||||
|
transport.WriteBufferSize = 16384
|
||||||
|
|
||||||
|
return &Agent{
|
||||||
|
AgentConfig: cfg,
|
||||||
|
httpClient: &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
},
|
||||||
|
fasthttpHcClient: &fasthttp.Client{
|
||||||
|
DialTimeout: func(addr string, timeout time.Duration) (net.Conn, error) {
|
||||||
|
if addr != agent.AgentHost+":443" {
|
||||||
|
return nil, &net.AddrError{Err: "invalid address", Addr: addr}
|
||||||
|
}
|
||||||
|
return net.DialTimeout("tcp", cfg.Addr, timeout)
|
||||||
|
},
|
||||||
|
TLSConfig: cfg.TLSConfig(),
|
||||||
|
ReadTimeout: 5 * time.Second,
|
||||||
|
WriteTimeout: 3 * time.Second,
|
||||||
|
DisableHeaderNamesNormalizing: true,
|
||||||
|
DisablePathNormalizing: true,
|
||||||
|
NoDefaultUserAgentHeader: true,
|
||||||
|
ReadBufferSize: 1024,
|
||||||
|
WriteBufferSize: 1024,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (agent *Agent) HTTPClient() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: agent.Transport(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package agent
|
package agentpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -10,22 +10,22 @@ import (
|
|||||||
"github.com/bytedance/sonic"
|
"github.com/bytedance/sonic"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
httputils "github.com/yusing/goutils/http"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
"github.com/yusing/goutils/http/reverseproxy"
|
"github.com/yusing/goutils/http/reverseproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (cfg *AgentConfig) Do(ctx context.Context, method, endpoint string, body io.Reader) (*http.Response, error) {
|
func (cfg *Agent) Do(ctx context.Context, method, endpoint string, body io.Reader) (*http.Response, error) {
|
||||||
req, err := http.NewRequestWithContext(ctx, method, APIBaseURL+endpoint, body)
|
req, err := http.NewRequestWithContext(ctx, method, agent.APIBaseURL+endpoint, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return cfg.httpClient.Do(req)
|
return cfg.httpClient.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AgentConfig) Forward(req *http.Request, endpoint string) (*http.Response, error) {
|
func (cfg *Agent) Forward(req *http.Request, endpoint string) (*http.Response, error) {
|
||||||
req.URL.Host = AgentHost
|
req.URL.Host = agent.AgentHost
|
||||||
req.URL.Scheme = "https"
|
req.URL.Scheme = "https"
|
||||||
req.URL.Path = APIEndpointBase + endpoint
|
req.URL.Path = agent.APIEndpointBase + endpoint
|
||||||
req.RequestURI = ""
|
req.RequestURI = ""
|
||||||
resp, err := cfg.httpClient.Do(req)
|
resp, err := cfg.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,20 +40,20 @@ type HealthCheckResponse struct {
|
|||||||
Latency time.Duration `json:"latency"`
|
Latency time.Duration `json:"latency"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AgentConfig) DoHealthCheck(timeout time.Duration, query string) (ret HealthCheckResponse, err error) {
|
func (cfg *Agent) DoHealthCheck(timeout time.Duration, query string) (ret HealthCheckResponse, err error) {
|
||||||
req := fasthttp.AcquireRequest()
|
req := fasthttp.AcquireRequest()
|
||||||
defer fasthttp.ReleaseRequest(req)
|
defer fasthttp.ReleaseRequest(req)
|
||||||
|
|
||||||
resp := fasthttp.AcquireResponse()
|
resp := fasthttp.AcquireResponse()
|
||||||
defer fasthttp.ReleaseResponse(resp)
|
defer fasthttp.ReleaseResponse(resp)
|
||||||
|
|
||||||
req.SetRequestURI(APIBaseURL + EndpointHealth + "?" + query)
|
req.SetRequestURI(agent.APIBaseURL + agent.EndpointHealth + "?" + query)
|
||||||
req.Header.SetMethod(fasthttp.MethodGet)
|
req.Header.SetMethod(fasthttp.MethodGet)
|
||||||
req.Header.Set("Accept-Encoding", "identity")
|
req.Header.Set("Accept-Encoding", "identity")
|
||||||
req.SetConnectionClose()
|
req.SetConnectionClose()
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err = cfg.fasthttpClientHealthCheck.DoTimeout(req, resp, timeout)
|
err = cfg.fasthttpHcClient.DoTimeout(req, resp, timeout)
|
||||||
ret.Latency = time.Since(start)
|
ret.Latency = time.Since(start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, err
|
return ret, err
|
||||||
@@ -71,30 +71,14 @@ func (cfg *AgentConfig) DoHealthCheck(timeout time.Duration, query string) (ret
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AgentConfig) fetchString(ctx context.Context, endpoint string) (string, int, error) {
|
func (cfg *Agent) Websocket(ctx context.Context, endpoint string) (*websocket.Conn, *http.Response, error) {
|
||||||
resp, err := cfg.Do(ctx, "GET", endpoint, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
data, release, err := httputils.ReadAllBody(resp)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
ret := string(data)
|
|
||||||
release(data)
|
|
||||||
return ret, resp.StatusCode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg *AgentConfig) Websocket(ctx context.Context, endpoint string) (*websocket.Conn, *http.Response, error) {
|
|
||||||
transport := cfg.Transport()
|
transport := cfg.Transport()
|
||||||
dialer := websocket.Dialer{
|
dialer := websocket.Dialer{
|
||||||
NetDialContext: transport.DialContext,
|
NetDialContext: transport.DialContext,
|
||||||
NetDialTLSContext: transport.DialTLSContext,
|
NetDialTLSContext: transport.DialTLSContext,
|
||||||
}
|
}
|
||||||
return dialer.DialContext(ctx, APIBaseURL+endpoint, http.Header{
|
return dialer.DialContext(ctx, agent.APIBaseURL+endpoint, http.Header{
|
||||||
"Host": {AgentHost},
|
"Host": {agent.AgentHost},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,9 +86,9 @@ func (cfg *AgentConfig) Websocket(ctx context.Context, endpoint string) (*websoc
|
|||||||
//
|
//
|
||||||
// It will create a new request with the same context, method, and body, but with the agent host and scheme, and the endpoint
|
// It will create a new request with the same context, method, and body, but with the agent host and scheme, and the endpoint
|
||||||
// If the request has a query, it will be added to the proxy request's URL
|
// If the request has a query, it will be added to the proxy request's URL
|
||||||
func (cfg *AgentConfig) ReverseProxy(w http.ResponseWriter, req *http.Request, endpoint string) {
|
func (cfg *Agent) ReverseProxy(w http.ResponseWriter, req *http.Request, endpoint string) {
|
||||||
rp := reverseproxy.NewReverseProxy("agent", AgentURL, cfg.Transport())
|
rp := reverseproxy.NewReverseProxy("agent", agent.AgentURL, cfg.Transport())
|
||||||
req.URL.Host = AgentHost
|
req.URL.Host = agent.AgentHost
|
||||||
req.URL.Scheme = "https"
|
req.URL.Scheme = "https"
|
||||||
req.URL.Path = endpoint
|
req.URL.Path = endpoint
|
||||||
req.RequestURI = ""
|
req.RequestURI = ""
|
||||||
79
internal/agentpool/pool.go
Normal file
79
internal/agentpool/pool.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package agentpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"iter"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/puzpuzpuz/xsync/v4"
|
||||||
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
)
|
||||||
|
|
||||||
|
var agentPool = xsync.NewMap[string, *Agent](xsync.WithPresize(10))
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if strings.HasSuffix(os.Args[0], ".test") {
|
||||||
|
agentPool.Store("test-agent", &Agent{
|
||||||
|
AgentConfig: &agent.AgentConfig{
|
||||||
|
Addr: "test-agent",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get(agentAddrOrDockerHost string) (*Agent, bool) {
|
||||||
|
if !agent.IsDockerHostAgent(agentAddrOrDockerHost) {
|
||||||
|
return getAgentByAddr(agentAddrOrDockerHost)
|
||||||
|
}
|
||||||
|
return getAgentByAddr(agent.GetAgentAddrFromDockerHost(agentAddrOrDockerHost))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAgent(name string) (*Agent, bool) {
|
||||||
|
for _, agent := range agentPool.Range {
|
||||||
|
if agent.Name == name {
|
||||||
|
return agent, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Add(cfg *agent.AgentConfig) (added bool) {
|
||||||
|
_, loaded := agentPool.LoadOrCompute(cfg.Addr, func() (*Agent, bool) {
|
||||||
|
return newAgent(cfg), false
|
||||||
|
})
|
||||||
|
return !loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
func Has(cfg *agent.AgentConfig) bool {
|
||||||
|
_, ok := agentPool.Load(cfg.Addr)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func Remove(cfg *agent.AgentConfig) {
|
||||||
|
agentPool.Delete(cfg.Addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveAll() {
|
||||||
|
agentPool.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func List() []*Agent {
|
||||||
|
agents := make([]*Agent, 0, agentPool.Size())
|
||||||
|
for _, agent := range agentPool.Range {
|
||||||
|
agents = append(agents, agent)
|
||||||
|
}
|
||||||
|
return agents
|
||||||
|
}
|
||||||
|
|
||||||
|
func Iter() iter.Seq2[string, *Agent] {
|
||||||
|
return agentPool.Range
|
||||||
|
}
|
||||||
|
|
||||||
|
func Num() int {
|
||||||
|
return agentPool.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAgentByAddr(addr string) (agent *Agent, ok bool) {
|
||||||
|
agent, ok = agentPool.Load(addr)
|
||||||
|
return agent, ok
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
apitypes "github.com/yusing/goutils/apitypes"
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ func Create(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostport := net.JoinHostPort(request.Host, strconv.Itoa(request.Port))
|
hostport := net.JoinHostPort(request.Host, strconv.Itoa(request.Port))
|
||||||
if _, ok := agent.GetAgent(hostport); ok {
|
if _, ok := agentpool.Get(hostport); ok {
|
||||||
c.JSON(http.StatusConflict, apitypes.Error("agent already exists"))
|
c.JSON(http.StatusConflict, apitypes.Error("agent already exists"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/goutils/http/httpheaders"
|
"github.com/yusing/goutils/http/httpheaders"
|
||||||
"github.com/yusing/goutils/http/websocket"
|
"github.com/yusing/goutils/http/websocket"
|
||||||
|
|
||||||
@@ -19,15 +19,15 @@ import (
|
|||||||
// @Tags agent,websocket
|
// @Tags agent,websocket
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} Agent
|
// @Success 200 {array} agent.AgentConfig
|
||||||
// @Failure 403 {object} apitypes.ErrorResponse
|
// @Failure 403 {object} apitypes.ErrorResponse
|
||||||
// @Router /agent/list [get]
|
// @Router /agent/list [get]
|
||||||
func List(c *gin.Context) {
|
func List(c *gin.Context) {
|
||||||
if httpheaders.IsWebsocket(c.Request.Header) {
|
if httpheaders.IsWebsocket(c.Request.Header) {
|
||||||
websocket.PeriodicWrite(c, 10*time.Second, func() (any, error) {
|
websocket.PeriodicWrite(c, 10*time.Second, func() (any, error) {
|
||||||
return agent.ListAgents(), nil
|
return agentpool.List(), nil
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
c.JSON(http.StatusOK, agent.ListAgents())
|
c.JSON(http.StatusOK, agentpool.List())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
"github.com/yusing/godoxy/agent/pkg/certs"
|
"github.com/yusing/godoxy/agent/pkg/certs"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
config "github.com/yusing/godoxy/internal/config/types"
|
config "github.com/yusing/godoxy/internal/config/types"
|
||||||
"github.com/yusing/godoxy/internal/route/provider"
|
"github.com/yusing/godoxy/internal/route/provider"
|
||||||
apitypes "github.com/yusing/goutils/apitypes"
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
@@ -79,21 +80,28 @@ func Verify(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, apitypes.Success(fmt.Sprintf("Added %d routes", nRoutesAdded)))
|
c.JSON(http.StatusOK, apitypes.Success(fmt.Sprintf("Added %d routes", nRoutesAdded)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyNewAgent(host string, ca agent.PEMPair, client agent.PEMPair, containerRuntime agent.ContainerRuntime) (int, gperr.Error) {
|
var errAgentAlreadyExists = gperr.New("agent already exists")
|
||||||
cfgState := config.ActiveState.Load()
|
|
||||||
for _, a := range cfgState.Value().Providers.Agents {
|
|
||||||
if a.Addr == host {
|
|
||||||
return 0, gperr.New("agent already exists")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
func verifyNewAgent(host string, ca agent.PEMPair, client agent.PEMPair, containerRuntime agent.ContainerRuntime) (int, gperr.Error) {
|
||||||
var agentCfg agent.AgentConfig
|
var agentCfg agent.AgentConfig
|
||||||
agentCfg.Addr = host
|
agentCfg.Addr = host
|
||||||
agentCfg.Runtime = containerRuntime
|
agentCfg.Runtime = containerRuntime
|
||||||
|
|
||||||
err := agentCfg.StartWithCerts(cfgState.Context(), ca.Cert, client.Cert, client.Key)
|
// check if agent host exists in the config
|
||||||
|
cfgState := config.ActiveState.Load()
|
||||||
|
for _, a := range cfgState.Value().Providers.Agents {
|
||||||
|
if a.Addr == host {
|
||||||
|
return 0, errAgentAlreadyExists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if agent host exists in the agent pool
|
||||||
|
if agentpool.Has(&agentCfg) {
|
||||||
|
return 0, errAgentAlreadyExists
|
||||||
|
}
|
||||||
|
|
||||||
|
err := agentCfg.InitWithCerts(cfgState.Context(), ca.Cert, client.Cert, client.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, gperr.Wrap(err, "failed to start agent")
|
return 0, gperr.Wrap(err, "failed to initialize agent config")
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := provider.NewAgentProvider(&agentCfg)
|
provider := provider.NewAgentProvider(&agentCfg)
|
||||||
@@ -102,11 +110,14 @@ func verifyNewAgent(host string, ca agent.PEMPair, client agent.PEMPair, contain
|
|||||||
}
|
}
|
||||||
|
|
||||||
// agent must be added before loading routes
|
// agent must be added before loading routes
|
||||||
agent.AddAgent(&agentCfg)
|
added := agentpool.Add(&agentCfg)
|
||||||
|
if !added {
|
||||||
|
return 0, errAgentAlreadyExists
|
||||||
|
}
|
||||||
err = provider.LoadRoutes()
|
err = provider.LoadRoutes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfgState.DeleteProvider(provider.String())
|
cfgState.DeleteProvider(provider.String())
|
||||||
agent.RemoveAgent(&agentCfg)
|
agentpool.Remove(&agentCfg)
|
||||||
return 0, gperr.Wrap(err, "failed to load routes")
|
return 0, gperr.Wrap(err, "failed to load routes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/metrics/period"
|
"github.com/yusing/godoxy/internal/metrics/period"
|
||||||
"github.com/yusing/godoxy/internal/metrics/systeminfo"
|
"github.com/yusing/godoxy/internal/metrics/systeminfo"
|
||||||
apitypes "github.com/yusing/goutils/apitypes"
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
@@ -79,7 +80,7 @@ func AllSystemInfo(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// leave 5 extra slots for buffering in case new agents are added.
|
// leave 5 extra slots for buffering in case new agents are added.
|
||||||
dataCh := make(chan SystemInfoData, 1+agent.NumAgents()+5)
|
dataCh := make(chan SystemInfoData, 1+agentpool.Num()+5)
|
||||||
defer close(dataCh)
|
defer close(dataCh)
|
||||||
|
|
||||||
ticker := time.NewTicker(req.Interval)
|
ticker := time.NewTicker(req.Interval)
|
||||||
@@ -125,7 +126,7 @@ func AllSystemInfo(c *gin.Context) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, a := range agent.IterAgents() {
|
for _, a := range agentpool.Iter() {
|
||||||
totalAgents++
|
totalAgents++
|
||||||
|
|
||||||
errs.Go(func() error {
|
errs.Go(func() error {
|
||||||
@@ -175,7 +176,7 @@ func AllSystemInfo(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAgentSystemInfo(ctx context.Context, a *agent.AgentConfig, query string) (bytesFromPool, error) {
|
func getAgentSystemInfo(ctx context.Context, a *agentpool.Agent, query string) (bytesFromPool, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ func getAgentSystemInfo(ctx context.Context, a *agent.AgentConfig, query string)
|
|||||||
return bytesFromPool{json.RawMessage(bytesBuf), release}, nil
|
return bytesFromPool{json.RawMessage(bytesBuf), release}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAgentSystemInfoWithRetry(ctx context.Context, a *agent.AgentConfig, query string) (bytesFromPool, error) {
|
func getAgentSystemInfoWithRetry(ctx context.Context, a *agentpool.Agent, query string) (bytesFromPool, error) {
|
||||||
const maxRetries = 3
|
const maxRetries = 3
|
||||||
var lastErr error
|
var lastErr error
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
agentPkg "github.com/yusing/godoxy/agent/pkg/agent"
|
agentPkg "github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/metrics/period"
|
"github.com/yusing/godoxy/internal/metrics/period"
|
||||||
"github.com/yusing/godoxy/internal/metrics/systeminfo"
|
"github.com/yusing/godoxy/internal/metrics/systeminfo"
|
||||||
apitypes "github.com/yusing/goutils/apitypes"
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
@@ -49,9 +50,9 @@ func SystemInfo(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
c.Request.URL.RawQuery = query.Encode()
|
c.Request.URL.RawQuery = query.Encode()
|
||||||
|
|
||||||
agent, ok := agentPkg.GetAgent(agentAddr)
|
agent, ok := agentpool.Get(agentAddr)
|
||||||
if !ok {
|
if !ok {
|
||||||
agent, ok = agentPkg.GetAgentByName(agentName)
|
agent, ok = agentpool.GetAgent(agentName)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
c.JSON(http.StatusNotFound, apitypes.Error("agent_addr or agent_name not found"))
|
c.JSON(http.StatusNotFound, apitypes.Error("agent_addr or agent_name not found"))
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import (
|
|||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/puzpuzpuz/xsync/v4"
|
"github.com/puzpuzpuz/xsync/v4"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
|
||||||
"github.com/yusing/godoxy/internal/acl"
|
"github.com/yusing/godoxy/internal/acl"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/autocert"
|
"github.com/yusing/godoxy/internal/autocert"
|
||||||
config "github.com/yusing/godoxy/internal/config/types"
|
config "github.com/yusing/godoxy/internal/config/types"
|
||||||
"github.com/yusing/godoxy/internal/entrypoint"
|
"github.com/yusing/godoxy/internal/entrypoint"
|
||||||
@@ -332,7 +332,7 @@ func (state *state) loadRouteProviders() error {
|
|||||||
errs := gperr.NewGroup("route provider errors")
|
errs := gperr.NewGroup("route provider errors")
|
||||||
results := gperr.NewGroup("loaded route providers")
|
results := gperr.NewGroup("loaded route providers")
|
||||||
|
|
||||||
agent.RemoveAllAgents()
|
agentpool.RemoveAll()
|
||||||
|
|
||||||
numProviders := len(providers.Agents) + len(providers.Files) + len(providers.Docker)
|
numProviders := len(providers.Agents) + len(providers.Files) + len(providers.Docker)
|
||||||
providersCh := make(chan types.RouteProvider, numProviders)
|
providersCh := make(chan types.RouteProvider, numProviders)
|
||||||
@@ -352,11 +352,11 @@ func (state *state) loadRouteProviders() error {
|
|||||||
var providersProducer sync.WaitGroup
|
var providersProducer sync.WaitGroup
|
||||||
for _, a := range providers.Agents {
|
for _, a := range providers.Agents {
|
||||||
providersProducer.Go(func() {
|
providersProducer.Go(func() {
|
||||||
if err := a.Start(state.task.Context()); err != nil {
|
if err := a.Init(state.task.Context()); err != nil {
|
||||||
errs.Add(gperr.PrependSubject(a.String(), err))
|
errs.Add(gperr.PrependSubject(a.String(), err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
agent.AddAgent(a)
|
agentpool.Add(a)
|
||||||
p := route.NewAgentProvider(a)
|
p := route.NewAgentProvider(a)
|
||||||
providersCh <- p
|
providersCh <- p
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/types"
|
"github.com/yusing/godoxy/internal/types"
|
||||||
httputils "github.com/yusing/goutils/http"
|
httputils "github.com/yusing/goutils/http"
|
||||||
"github.com/yusing/goutils/task"
|
"github.com/yusing/goutils/task"
|
||||||
@@ -149,17 +150,16 @@ func NewClient(cfg types.DockerProviderConfig, unique ...bool) (*SharedClient, e
|
|||||||
var dial func(ctx context.Context) (net.Conn, error)
|
var dial func(ctx context.Context) (net.Conn, error)
|
||||||
|
|
||||||
if agent.IsDockerHostAgent(host) {
|
if agent.IsDockerHostAgent(host) {
|
||||||
cfg, ok := agent.GetAgent(host)
|
a, ok := agentpool.Get(host)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Errorf("agent %q not found", host))
|
panic(fmt.Errorf("agent %q not found", host))
|
||||||
}
|
}
|
||||||
opt = []client.Opt{
|
opt = []client.Opt{
|
||||||
client.WithHost(agent.DockerHost),
|
client.WithHost(agent.DockerHost),
|
||||||
client.WithHTTPClient(cfg.NewHTTPClient()),
|
client.WithHTTPClient(a.HTTPClient()),
|
||||||
client.WithAPIVersionNegotiation(),
|
|
||||||
}
|
}
|
||||||
addr = "tcp://" + cfg.Addr
|
addr = "tcp://" + a.Addr
|
||||||
dial = cfg.DialContext
|
dial = a.DialContext
|
||||||
} else {
|
} else {
|
||||||
helper, err := connhelper.GetConnectionHelper(host)
|
helper, err := connhelper.GetConnectionHelper(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/agent/pkg/agent"
|
||||||
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/serialization"
|
"github.com/yusing/godoxy/internal/serialization"
|
||||||
"github.com/yusing/godoxy/internal/types"
|
"github.com/yusing/godoxy/internal/types"
|
||||||
gperr "github.com/yusing/goutils/errs"
|
gperr "github.com/yusing/goutils/errs"
|
||||||
@@ -70,7 +71,7 @@ func FromDocker(c *container.Summary, dockerCfg types.DockerProviderConfig) (res
|
|||||||
|
|
||||||
if agent.IsDockerHostAgent(dockerCfg.URL) {
|
if agent.IsDockerHostAgent(dockerCfg.URL) {
|
||||||
var ok bool
|
var ok bool
|
||||||
res.Agent, ok = agent.GetAgent(dockerCfg.URL)
|
res.Agent, ok = agentpool.Get(dockerCfg.URL)
|
||||||
if !ok {
|
if !ok {
|
||||||
addError(res, fmt.Errorf("agent %q not found", dockerCfg.URL))
|
addError(res, fmt.Errorf("agent %q not found", dockerCfg.URL))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
config "github.com/yusing/godoxy/internal/config/types"
|
config "github.com/yusing/godoxy/internal/config/types"
|
||||||
"github.com/yusing/godoxy/internal/docker"
|
"github.com/yusing/godoxy/internal/docker"
|
||||||
"github.com/yusing/godoxy/internal/homepage"
|
"github.com/yusing/godoxy/internal/homepage"
|
||||||
@@ -95,7 +95,7 @@ type (
|
|||||||
|
|
||||||
provider types.RouteProvider
|
provider types.RouteProvider
|
||||||
|
|
||||||
agent *agent.AgentConfig
|
agent *agentpool.Agent
|
||||||
|
|
||||||
started chan struct{}
|
started chan struct{}
|
||||||
onceStart sync.Once
|
onceStart sync.Once
|
||||||
@@ -154,10 +154,10 @@ func (r *Route) validate() gperr.Error {
|
|||||||
}
|
}
|
||||||
var ok bool
|
var ok bool
|
||||||
// by agent address
|
// by agent address
|
||||||
r.agent, ok = agent.GetAgent(r.Agent)
|
r.agent, ok = agentpool.Get(r.Agent)
|
||||||
if !ok {
|
if !ok {
|
||||||
// fallback to get agent by name
|
// fallback to get agent by name
|
||||||
r.agent, ok = agent.GetAgentByName(r.Agent)
|
r.agent, ok = agentpool.GetAgent(r.Agent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return gperr.Errorf("agent %s not found", r.Agent)
|
return gperr.Errorf("agent %s not found", r.Agent)
|
||||||
}
|
}
|
||||||
@@ -511,7 +511,7 @@ func (r *Route) Type() route.RouteType {
|
|||||||
panic(fmt.Errorf("unexpected scheme %s for alias %s", r.Scheme, r.Alias))
|
panic(fmt.Errorf("unexpected scheme %s for alias %s", r.Scheme, r.Alias))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) GetAgent() *agent.AgentConfig {
|
func (r *Route) GetAgent() *agentpool.Agent {
|
||||||
if r.Container != nil && r.Container.Agent != nil {
|
if r.Container != nil && r.Container.Agent != nil {
|
||||||
return r.Container.Agent
|
return r.Container.Agent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/bytedance/sonic"
|
"github.com/bytedance/sonic"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/yusing/ds/ordered"
|
"github.com/yusing/ds/ordered"
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
gperr "github.com/yusing/goutils/errs"
|
gperr "github.com/yusing/goutils/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ type (
|
|||||||
|
|
||||||
State container.ContainerState `json:"state"`
|
State container.ContainerState `json:"state"`
|
||||||
|
|
||||||
Agent *agent.AgentConfig `json:"agent"`
|
Agent *agentpool.Agent `json:"agent"`
|
||||||
|
|
||||||
Labels map[string]string `json:"-"` // for creating routes
|
Labels map[string]string `json:"-"` // for creating routes
|
||||||
ActualLabels map[string]string `json:"labels"` // for displaying in UI
|
ActualLabels map[string]string `json:"labels"` // for displaying in UI
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package types
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/homepage"
|
"github.com/yusing/godoxy/internal/homepage"
|
||||||
nettypes "github.com/yusing/godoxy/internal/net/types"
|
nettypes "github.com/yusing/godoxy/internal/net/types"
|
||||||
provider "github.com/yusing/godoxy/internal/route/provider/types"
|
provider "github.com/yusing/godoxy/internal/route/provider/types"
|
||||||
@@ -35,7 +35,7 @@ type (
|
|||||||
DisplayName() string
|
DisplayName() string
|
||||||
ContainerInfo() *Container
|
ContainerInfo() *Container
|
||||||
|
|
||||||
GetAgent() *agent.AgentConfig
|
GetAgent() *agentpool.Agent
|
||||||
|
|
||||||
IsDocker() bool
|
IsDocker() bool
|
||||||
IsAgent() bool
|
IsAgent() bool
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package monitor
|
|||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
agentPkg "github.com/yusing/godoxy/agent/pkg/agent"
|
"github.com/yusing/godoxy/internal/agentpool"
|
||||||
"github.com/yusing/godoxy/internal/types"
|
"github.com/yusing/godoxy/internal/types"
|
||||||
"github.com/yusing/goutils/synk"
|
"github.com/yusing/goutils/synk"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
AgentProxiedMonitor struct {
|
AgentProxiedMonitor struct {
|
||||||
agent *agentPkg.AgentConfig
|
agent *agentpool.Agent
|
||||||
query synk.Value[string]
|
query synk.Value[string]
|
||||||
*monitor
|
*monitor
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func (target *AgentCheckHealthTarget) displayURL() *url.URL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAgentProxiedMonitor(agent *agentPkg.AgentConfig, config types.HealthCheckConfig, target *AgentCheckHealthTarget) *AgentProxiedMonitor {
|
func NewAgentProxiedMonitor(agent *agentpool.Agent, config types.HealthCheckConfig, target *AgentCheckHealthTarget) *AgentProxiedMonitor {
|
||||||
mon := &AgentProxiedMonitor{
|
mon := &AgentProxiedMonitor{
|
||||||
agent: agent,
|
agent: agent,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user