feat(agent): allow specifying agent for routes in route files

This commit is contained in:
yusing 2025-06-14 20:05:11 +08:00
parent 7d17a01de1
commit 5ce1c7865e
2 changed files with 66 additions and 10 deletions

View file

@ -50,6 +50,7 @@ type (
Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"` Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"`
Homepage *homepage.ItemConfig `json:"homepage,omitempty"` Homepage *homepage.ItemConfig `json:"homepage,omitempty"`
AccessLog *accesslog.RequestLoggerConfig `json:"access_log,omitempty"` AccessLog *accesslog.RequestLoggerConfig `json:"access_log,omitempty"`
Agent string `json:"agent,omitempty"`
Idlewatcher *idlewatcher.Config `json:"idlewatcher,omitempty"` Idlewatcher *idlewatcher.Config `json:"idlewatcher,omitempty"`
HealthMon health.HealthMonitor `json:"health,omitempty"` HealthMon health.HealthMonitor `json:"health,omitempty"`
@ -76,6 +77,8 @@ type (
lastError gperr.Error lastError gperr.Error
provider routes.Provider provider routes.Provider
agent *agent.AgentConfig
started chan struct{} started chan struct{}
once sync.Once once sync.Once
} }
@ -94,6 +97,23 @@ func (r *Route) Validate() gperr.Error {
return r.lastError return r.lastError
} }
r.isValidated = true r.isValidated = true
if r.Agent != "" {
if r.Container != nil {
return gperr.Errorf("specifying agent is not allowed for docker container routes")
}
var ok bool
// by agent address
r.agent, ok = agent.GetAgent(r.Agent)
if !ok {
// fallback to get agent by name
r.agent, ok = agent.GetAgentByName(r.Agent)
if !ok {
return gperr.Errorf("agent %s not found", r.Agent)
}
}
}
r.Finalize() r.Finalize()
r.started = make(chan struct{}) r.started = make(chan struct{})
@ -177,13 +197,15 @@ func (r *Route) Validate() gperr.Error {
r.Idlewatcher = r.Container.IdlewatcherConfig r.Idlewatcher = r.Container.IdlewatcherConfig
} }
// return error if route is localhost:<godoxy_port> // return error if route is localhost:<godoxy_port> but route is not agent
switch r.Host { if !r.IsAgent() {
case "localhost", "127.0.0.1": switch r.Host {
switch r.Port.Proxy { case "localhost", "127.0.0.1":
case common.ProxyHTTPPort, common.ProxyHTTPSPort, common.APIHTTPPort: switch r.Port.Proxy {
if r.Scheme.IsReverseProxy() || r.Scheme == route.SchemeTCP { case common.ProxyHTTPPort, common.ProxyHTTPSPort, common.APIHTTPPort:
return gperr.Errorf("localhost:%d is reserved for godoxy", r.Port.Proxy) if r.Scheme.IsReverseProxy() || r.Scheme == route.SchemeTCP {
return gperr.Errorf("localhost:%d is reserved for godoxy", r.Port.Proxy)
}
} }
} }
} }
@ -352,10 +374,10 @@ func (r *Route) Type() route.RouteType {
} }
func (r *Route) GetAgent() *agent.AgentConfig { func (r *Route) GetAgent() *agent.AgentConfig {
if r.Container == nil { if r.Container != nil && r.Container.Agent != nil {
return nil return r.Container.Agent
} }
return r.Container.Agent return r.agent
} }
func (r *Route) IsAgent() bool { func (r *Route) IsAgent() bool {

View file

@ -148,3 +148,37 @@ func TestPreferredPort(t *testing.T) {
port := preferredPort(ports) port := preferredPort(ports)
expect.Equal(t, port, 3000) expect.Equal(t, port, 3000)
} }
func TestDockerRouteDisallowAgent(t *testing.T) {
r := &Route{
Alias: "test",
Scheme: route.SchemeHTTP,
Host: "example.com",
Port: route.Port{Proxy: 80},
Agent: "test-agent",
Metadata: Metadata{
Container: &docker.Container{
ContainerID: "test-id",
Image: &docker.ContainerImage{
Name: "test-image",
},
},
},
}
err := r.Validate()
expect.HasError(t, err, "Validate should return error for docker route with agent")
expect.ErrorContains(t, err, "specifying agent is not allowed for docker container routes")
}
func TestRouteAgent(t *testing.T) {
r := &Route{
Alias: "test",
Scheme: route.SchemeHTTP,
Host: "example.com",
Port: route.Port{Proxy: 80},
Agent: "test-agent",
}
err := r.Validate()
expect.NoError(t, err, "Validate should not return error for valid route with agent")
expect.NotNil(t, r.GetAgent(), "GetAgent should return agent")
}