From 4e19cd15659c29b9e6a320d51a2d17da75f80960 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 12 Mar 2026 23:09:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20RuntimeRouteConfig?= =?UTF-8?q?Path=20=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98=E5=8C=96=20Nginx=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atsf_agent/cmd/agent/main.go | 13 +++++--- atsf_agent/internal/nginx/manager.go | 28 ++++++++++------ atsf_agent/internal/nginx/manager_test.go | 39 +++++++++++++++++++++++ 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/atsf_agent/cmd/agent/main.go b/atsf_agent/cmd/agent/main.go index 5c08325e..d7c4e761 100644 --- a/atsf_agent/cmd/agent/main.go +++ b/atsf_agent/cmd/agent/main.go @@ -42,11 +42,16 @@ func main() { client := httpclient.New(cfg.ServerURL, cfg.InitialAuthToken(), cfg.RequestTimeout.Duration()) stateStore := state.NewStore(cfg.StatePath) + runtimeRouteConfigPath := cfg.RouteConfigPath + if cfg.OpenrestyPath == "" { + runtimeRouteConfigPath = nginx.DockerRouteConfigPath + } runtimeManager := &nginx.Manager{ - MainConfigPath: cfg.MainConfigPath, - RouteConfigPath: cfg.RouteConfigPath, - CertDir: cfg.CertDir, - NginxCertDir: cfg.OpenrestyCertDir, + MainConfigPath: cfg.MainConfigPath, + RouteConfigPath: cfg.RouteConfigPath, + RuntimeRouteConfigPath: runtimeRouteConfigPath, + CertDir: cfg.CertDir, + NginxCertDir: cfg.OpenrestyCertDir, Executor: nginx.NewExecutor(nginx.ExecutorOptions{ NginxPath: cfg.OpenrestyPath, DockerBinary: cfg.DockerBinary, diff --git a/atsf_agent/internal/nginx/manager.go b/atsf_agent/internal/nginx/manager.go index 811a41f3..c820941b 100644 --- a/atsf_agent/internal/nginx/manager.go +++ b/atsf_agent/internal/nginx/manager.go @@ -20,6 +20,7 @@ import ( const CertDirPlaceholder = "__ATSF_CERT_DIR__" const RouteConfigPlaceholder = "__ATSF_ROUTE_CONFIG__" const DockerMainConfigPath = "/usr/local/openresty/nginx/conf/nginx.conf" +const DockerRouteConfigPath = "/etc/nginx/conf.d/atsflare_routes.conf" const dockerRuntimeCommand = "openresty" @@ -191,11 +192,12 @@ func (e *DockerExecutor) runContainer(ctx context.Context) error { } type Manager struct { - MainConfigPath string - RouteConfigPath string - CertDir string - NginxCertDir string - Executor Executor + MainConfigPath string + RouteConfigPath string + RuntimeRouteConfigPath string + CertDir string + NginxCertDir string + Executor Executor } func (m *Manager) Apply(ctx context.Context, mainConfig string, routeConfig string, supportFiles []protocol.SupportFile) error { @@ -280,8 +282,8 @@ func (m *Manager) CurrentChecksum() (string, error) { return "", err } normalizedMain := string(mainData) - if m.RouteConfigPath != "" { - normalizedMain = strings.ReplaceAll(normalizedMain, m.RouteConfigPath, RouteConfigPlaceholder) + if includePath := m.routeConfigIncludePath(); includePath != "" { + normalizedMain = strings.ReplaceAll(normalizedMain, includePath, RouteConfigPlaceholder) } normalizedRoute := string(data) if m.NginxCertDir != "" { @@ -579,10 +581,18 @@ func (m *Manager) renderRouteConfig(content string) string { } func (m *Manager) renderMainConfig(content string) string { - if m.RouteConfigPath == "" { + includePath := m.routeConfigIncludePath() + if includePath == "" { return content } - return strings.ReplaceAll(content, RouteConfigPlaceholder, m.RouteConfigPath) + return strings.ReplaceAll(content, RouteConfigPlaceholder, includePath) +} + +func (m *Manager) routeConfigIncludePath() string { + if strings.TrimSpace(m.RuntimeRouteConfigPath) != "" { + return strings.TrimSpace(m.RuntimeRouteConfigPath) + } + return strings.TrimSpace(m.RouteConfigPath) } func checksum(content string) string { diff --git a/atsf_agent/internal/nginx/manager_test.go b/atsf_agent/internal/nginx/manager_test.go index eeb9e579..7411d664 100644 --- a/atsf_agent/internal/nginx/manager_test.go +++ b/atsf_agent/internal/nginx/manager_test.go @@ -371,6 +371,45 @@ func TestManagerApplyAndChecksumIncludeMainConfig(t *testing.T) { } } +func TestManagerApplyUsesRuntimeRouteConfigPath(t *testing.T) { + tempDir := t.TempDir() + mainPath := filepath.Join(tempDir, "nginx.conf") + routePath := filepath.Join(tempDir, "conf.d", "atsflare_routes.conf") + manager := &Manager{ + MainConfigPath: mainPath, + RouteConfigPath: routePath, + RuntimeRouteConfigPath: DockerRouteConfigPath, + CertDir: filepath.Join(tempDir, "certs"), + NginxCertDir: "/etc/nginx/atsflare-certs", + Executor: &fakeExecutor{}, + } + + if err := manager.Apply(context.Background(), "include __ATSF_ROUTE_CONFIG__;\n", "server { listen 80; }\n", nil); err != nil { + t.Fatalf("Apply failed: %v", err) + } + + mainData, err := os.ReadFile(mainPath) + if err != nil { + t.Fatalf("failed to read main config: %v", err) + } + if string(mainData) != "include "+DockerRouteConfigPath+";\n" { + t.Fatalf("unexpected main config include path: %s", string(mainData)) + } + + value, err := manager.CurrentChecksum() + if err != nil { + t.Fatalf("CurrentChecksum failed: %v", err) + } + expected := bundleChecksum( + "include __ATSF_ROUTE_CONFIG__;\n", + "server { listen 80; }\n", + nil, + ) + if value != expected { + t.Fatalf("unexpected checksum: got %s want %s", value, expected) + } +} + func TestDetectVersionFromDockerImage(t *testing.T) { runner := &fakeRunner{ runFn: func(name string, args ...string) ([]byte, error) {