mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 16:46:37 +08:00
[新增] Agent 架构调整, 采用集成镜像方式
This commit is contained in:
@@ -24,15 +24,11 @@ const CertDirPlaceholder = "__OPENFLARE_CERT_DIR__"
|
||||
const RouteConfigPlaceholder = "__OPENFLARE_ROUTE_CONFIG__"
|
||||
const AccessLogPlaceholder = "__OPENFLARE_ACCESS_LOG__"
|
||||
const LuaDirPlaceholder = "__OPENFLARE_LUA_DIR__"
|
||||
const RuntimeConfigDirPlaceholder = "__OPENFLARE_RUNTIME_CONFIG_DIR__"
|
||||
const ObservabilityListenPlaceholder = "__OPENFLARE_OBSERVABILITY_LISTEN__"
|
||||
const ObservabilityPortPlaceholder = "__OPENFLARE_OBSERVABILITY_PORT__"
|
||||
const ResolverDirectivePlaceholder = "__OPENFLARE_RESOLVER_DIRECTIVE__"
|
||||
const PowStaticDirPlaceholder = "__OPENFLARE_POW_STATIC_DIR__"
|
||||
const DockerMainConfigPath = "/usr/local/openresty/nginx/conf/nginx.conf"
|
||||
const DockerRouteConfigPath = "/etc/nginx/conf.d/openflare_routes.conf"
|
||||
const DockerAccessLogPath = "/etc/nginx/conf.d/openflare_access.log"
|
||||
|
||||
const dockerRuntimeCommand = "openresty"
|
||||
|
||||
type Executor interface {
|
||||
Test(ctx context.Context) error
|
||||
@@ -55,13 +51,14 @@ func (r *OSCommandRunner) Run(ctx context.Context, name string, args ...string)
|
||||
}
|
||||
|
||||
type PathExecutor struct {
|
||||
Path string
|
||||
Runner CommandRunner
|
||||
Path string
|
||||
ConfigPath string
|
||||
Runner CommandRunner
|
||||
}
|
||||
|
||||
func (e *PathExecutor) Test(ctx context.Context) error {
|
||||
slog.Debug("running openresty test with binary", "path", e.Path)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-t")
|
||||
slog.Debug("running openresty test with binary", "path", e.Path, "config", e.ConfigPath)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-t", "-c", e.ConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("openresty -t failed: %w: %s", err, string(output))
|
||||
}
|
||||
@@ -70,9 +67,17 @@ func (e *PathExecutor) Test(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (e *PathExecutor) Reload(ctx context.Context) error {
|
||||
slog.Debug("running openresty reload with binary", "path", e.Path)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-s", "reload")
|
||||
slog.Debug("running openresty reload with binary", "path", e.Path, "config", e.ConfigPath)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-s", "reload", "-c", e.ConfigPath)
|
||||
if err != nil {
|
||||
if isOpenrestyNotRunningError(string(output)) {
|
||||
slog.Warn("openresty reload reported runtime is not running, starting binary", "path", e.Path)
|
||||
startOutput, startErr := e.Runner.Run(ctx, e.Path, "-c", e.ConfigPath)
|
||||
if startErr != nil {
|
||||
return fmt.Errorf("openresty reload failed: %w: %s; start failed: %v: %s", err, string(output), startErr, string(startOutput))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("openresty reload failed: %w: %s", err, string(output))
|
||||
}
|
||||
slog.Debug("openresty reload succeeded with binary", "path", e.Path)
|
||||
@@ -80,7 +85,10 @@ func (e *PathExecutor) Reload(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (e *PathExecutor) EnsureRuntime(ctx context.Context, recreate bool) error {
|
||||
return nil
|
||||
if err := e.Test(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.Reload(ctx)
|
||||
}
|
||||
|
||||
func (e *PathExecutor) CheckHealth(ctx context.Context) error {
|
||||
@@ -88,15 +96,15 @@ func (e *PathExecutor) CheckHealth(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (e *PathExecutor) Restart(ctx context.Context) error {
|
||||
slog.Info("restarting openresty with binary", "path", e.Path)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-s", "quit")
|
||||
slog.Info("restarting openresty with binary", "path", e.Path, "config", e.ConfigPath)
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-s", "quit", "-c", e.ConfigPath)
|
||||
if err != nil {
|
||||
text := string(output)
|
||||
if !isIgnorableOpenrestyStopError(text) {
|
||||
return fmt.Errorf("openresty stop failed: %w: %s", err, text)
|
||||
}
|
||||
}
|
||||
output, err = e.Runner.Run(ctx, e.Path)
|
||||
output, err = e.Runner.Run(ctx, e.Path, "-c", e.ConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("openresty start failed: %w: %s", err, string(output))
|
||||
}
|
||||
@@ -104,258 +112,15 @@ func (e *PathExecutor) Restart(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DockerExecutor struct {
|
||||
DockerBinary string
|
||||
ContainerName string
|
||||
Image string
|
||||
MainConfigPath string
|
||||
RouteConfigDir string
|
||||
CertDir string
|
||||
NginxCertDir string
|
||||
LuaDir string
|
||||
NginxLuaDir string
|
||||
OpenrestyObservabilityPort int
|
||||
Runner CommandRunner
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) Test(ctx context.Context) error {
|
||||
slog.Debug("running docker openresty test", "container", e.ContainerName, "image", e.Image)
|
||||
if err := e.validateMountSources(); err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := e.runEphemeralRuntimeCommand(ctx, "-t")
|
||||
if err != nil {
|
||||
return fmt.Errorf("docker %s -t failed: %w: %s", dockerRuntimeCommand, err, string(output))
|
||||
}
|
||||
slog.Debug("docker openresty test succeeded", "container", e.ContainerName, "runtime", dockerRuntimeCommand)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) Reload(ctx context.Context) error {
|
||||
if err := e.validateMountSources(); err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "inspect", "-f", "{{.State.Running}}", e.ContainerName)
|
||||
if err != nil || strings.TrimSpace(string(output)) != "true" {
|
||||
return e.EnsureRuntime(ctx, false)
|
||||
}
|
||||
output, err = e.Runner.Run(ctx, e.DockerBinary, "exec", e.ContainerName, dockerRuntimeCommand, "-s", "reload")
|
||||
if err != nil {
|
||||
if e.shouldRecreateAfterReloadFailure(string(output)) {
|
||||
slog.Warn("docker openresty reload failed due to missing mounted files, recreating container", "container", e.ContainerName)
|
||||
if recreateErr := e.EnsureRuntime(ctx, true); recreateErr != nil {
|
||||
return fmt.Errorf("docker exec %s reload failed: %w: %s; recreate failed: %v", dockerRuntimeCommand, err, string(output), recreateErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("docker exec %s reload failed: %w: %s", dockerRuntimeCommand, err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) EnsureRuntime(ctx context.Context, recreate bool) error {
|
||||
slog.Info("ensuring docker openresty runtime", "container", e.ContainerName, "recreate", recreate)
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "inspect", "-f", "{{.State.Running}}", e.ContainerName)
|
||||
if err == nil {
|
||||
if recreate {
|
||||
if err := e.removeContainer(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.runContainer(ctx)
|
||||
}
|
||||
if strings.TrimSpace(string(output)) == "true" {
|
||||
slog.Debug("docker openresty runtime already healthy", "container", e.ContainerName)
|
||||
return nil
|
||||
}
|
||||
if err := e.removeContainer(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.runContainer(ctx)
|
||||
}
|
||||
return e.runContainer(ctx)
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) CheckHealth(ctx context.Context) error {
|
||||
slog.Debug("checking docker openresty runtime health", "container", e.ContainerName)
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "inspect", "-f", "{{.State.Running}}", e.ContainerName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("docker inspect openresty failed: %w: %s", err, string(output))
|
||||
}
|
||||
if strings.TrimSpace(string(output)) != "true" {
|
||||
return e.containerNotRunningError(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) Restart(ctx context.Context) error {
|
||||
return e.EnsureRuntime(ctx, true)
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) removeContainer(ctx context.Context) error {
|
||||
slog.Info("removing docker openresty container", "container", e.ContainerName)
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "rm", "-f", e.ContainerName)
|
||||
if err != nil {
|
||||
text := string(output)
|
||||
if strings.Contains(text, "No such container") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("docker rm openresty failed: %w: %s", err, text)
|
||||
}
|
||||
slog.Info("docker openresty container removed", "container", e.ContainerName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) runContainer(ctx context.Context) error {
|
||||
slog.Info("starting docker openresty container", "container", e.ContainerName, "image", e.Image)
|
||||
if err := e.validateMountSources(); err != nil {
|
||||
return err
|
||||
}
|
||||
runArgs := []string{
|
||||
"run", "-d",
|
||||
"--name", e.ContainerName,
|
||||
"--restart", "always",
|
||||
"-p", "80:80",
|
||||
"-p", "443:443",
|
||||
"-p", fmt.Sprintf("127.0.0.1:%d:%d", e.OpenrestyObservabilityPort, e.OpenrestyObservabilityPort),
|
||||
"-v", fmt.Sprintf("%s:%s", e.MainConfigPath, DockerMainConfigPath),
|
||||
"-v", fmt.Sprintf("%s:/etc/nginx/conf.d", e.RouteConfigDir),
|
||||
"-v", fmt.Sprintf("%s:%s", e.CertDir, e.NginxCertDir),
|
||||
"-v", fmt.Sprintf("%s:%s", e.LuaDir, e.NginxLuaDir),
|
||||
e.Image,
|
||||
}
|
||||
runOutput, runErr := e.Runner.Run(ctx, e.DockerBinary, runArgs...)
|
||||
if runErr != nil {
|
||||
return fmt.Errorf("docker run openresty failed: %w: %s", runErr, string(runOutput))
|
||||
}
|
||||
if err := e.CheckHealth(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
slog.Info("docker openresty container started", "container", e.ContainerName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) validateMountSources() error {
|
||||
if err := ensureRegularFile(e.MainConfigPath, "openresty main config"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureDirectory(e.RouteConfigDir, "openresty route config dir"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureDirectory(e.CertDir, "openresty cert dir"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureDirectory(e.LuaDir, "openresty lua dir"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) shouldRecreateAfterReloadFailure(output string) bool {
|
||||
text := strings.ToLower(strings.TrimSpace(output))
|
||||
if text == "" {
|
||||
return false
|
||||
}
|
||||
if !strings.Contains(text, "no such file") && !strings.Contains(text, "cannot load certificate") {
|
||||
return false
|
||||
}
|
||||
paths := []string{
|
||||
strings.ToLower(e.NginxCertDir),
|
||||
strings.ToLower(e.NginxLuaDir),
|
||||
strings.ToLower(DockerMainConfigPath),
|
||||
strings.ToLower("/etc/nginx/conf.d"),
|
||||
}
|
||||
for _, path := range paths {
|
||||
if strings.TrimSpace(path) != "" && strings.Contains(text, path) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) containerNotRunningError(ctx context.Context) error {
|
||||
inspectSummary := ""
|
||||
inspectOutput, inspectErr := e.Runner.Run(ctx, e.DockerBinary, "inspect", "-f", "status={{.State.Status}} exit_code={{.State.ExitCode}} error={{printf \"%q\" .State.Error}} oom_killed={{.State.OOMKilled}} finished_at={{.State.FinishedAt}}", e.ContainerName)
|
||||
if inspectErr == nil {
|
||||
inspectSummary = strings.TrimSpace(string(inspectOutput))
|
||||
}
|
||||
|
||||
logTail := ""
|
||||
logOutput, logErr := e.Runner.Run(ctx, e.DockerBinary, "logs", "--tail", "50", e.ContainerName)
|
||||
if logErr == nil {
|
||||
logTail = strings.TrimSpace(string(logOutput))
|
||||
}
|
||||
|
||||
message := "docker openresty container is not running"
|
||||
if inspectSummary != "" {
|
||||
message += ": " + inspectSummary
|
||||
}
|
||||
if logTail != "" {
|
||||
message += "; recent logs: " + compactDiagnosticText(logTail)
|
||||
}
|
||||
return errors.New(message)
|
||||
}
|
||||
|
||||
func compactDiagnosticText(text string) string {
|
||||
trimmed := strings.TrimSpace(text)
|
||||
if trimmed == "" {
|
||||
return ""
|
||||
}
|
||||
lines := strings.Split(trimmed, "\n")
|
||||
if len(lines) > 8 {
|
||||
lines = lines[len(lines)-8:]
|
||||
}
|
||||
joined := strings.Join(lines, " | ")
|
||||
joined = strings.Join(strings.Fields(joined), " ")
|
||||
if len(joined) > 800 {
|
||||
return joined[len(joined)-800:]
|
||||
}
|
||||
return joined
|
||||
}
|
||||
|
||||
func ensureRegularFile(path string, label string) error {
|
||||
cleanPath := strings.TrimSpace(path)
|
||||
if cleanPath == "" {
|
||||
return fmt.Errorf("%s path is empty", label)
|
||||
}
|
||||
info, err := os.Stat(cleanPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("%s %q does not exist; run a config apply first so Docker does not create a directory mount source", label, cleanPath)
|
||||
}
|
||||
return fmt.Errorf("stat %s %q failed: %w", label, cleanPath, err)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("%s %q is a directory; expected a file for Docker bind mount", label, cleanPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureDirectory(path string, label string) error {
|
||||
cleanPath := strings.TrimSpace(path)
|
||||
if cleanPath == "" {
|
||||
return fmt.Errorf("%s path is empty", label)
|
||||
}
|
||||
info, err := os.Stat(cleanPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("%s %q does not exist; expected a directory for Docker bind mount", label, cleanPath)
|
||||
}
|
||||
return fmt.Errorf("stat %s %q failed: %w", label, cleanPath, err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("%s %q is not a directory; expected a directory for Docker bind mount", label, cleanPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
MainConfigPath string
|
||||
RouteConfigPath string
|
||||
RuntimeRouteConfigPath string
|
||||
AccessLogPath string
|
||||
CertDir string
|
||||
NginxCertDir string
|
||||
LuaDir string
|
||||
NginxLuaDir string
|
||||
RuntimeConfigDir string
|
||||
OpenrestyObservabilityListen string
|
||||
OpenrestyObservabilityPort int
|
||||
OpenrestyResolverDirective string
|
||||
@@ -419,8 +184,8 @@ func (m *Manager) activateConfig(ctx context.Context) error {
|
||||
if m.Executor == nil {
|
||||
return errors.New("executor 未配置")
|
||||
}
|
||||
if _, ok := m.Executor.(*DockerExecutor); ok {
|
||||
return m.Executor.EnsureRuntime(ctx, true)
|
||||
if err := m.Executor.Test(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.Executor.Reload(ctx)
|
||||
}
|
||||
@@ -455,14 +220,7 @@ func (m *Manager) EnsureLuaAssets() error {
|
||||
if strings.TrimSpace(m.LuaDir) == "" {
|
||||
return nil
|
||||
}
|
||||
allSupportFiles := append(ManagedObservabilityLuaFiles(), ManagedPowLuaFiles()...)
|
||||
existingPowConfig, err := m.readPowConfigFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existingPowConfig != nil {
|
||||
allSupportFiles = append(allSupportFiles, *existingPowConfig)
|
||||
}
|
||||
allSupportFiles := append(ManagedObservabilityLuaFiles(), m.managedPowLuaFiles()...)
|
||||
powStaticFiles, err := ManagedPowStaticFiles()
|
||||
if err != nil {
|
||||
return fmt.Errorf("load pow static files: %w", err)
|
||||
@@ -569,9 +327,6 @@ func (m *Manager) CurrentChecksum() (string, error) {
|
||||
|
||||
type ExecutorOptions struct {
|
||||
NginxPath string
|
||||
DockerBinary string
|
||||
ContainerName string
|
||||
Image string
|
||||
MainConfigPath string
|
||||
RouteConfigPath string
|
||||
CertDir string
|
||||
@@ -583,48 +338,10 @@ type ExecutorOptions struct {
|
||||
|
||||
func NewExecutor(options ExecutorOptions) Executor {
|
||||
runner := &OSCommandRunner{}
|
||||
if options.NginxPath != "" {
|
||||
return &PathExecutor{
|
||||
Path: options.NginxPath,
|
||||
Runner: runner,
|
||||
}
|
||||
}
|
||||
mainConfigPath := options.MainConfigPath
|
||||
if mainConfigPath != "" {
|
||||
if absPath, err := filepath.Abs(mainConfigPath); err == nil {
|
||||
mainConfigPath = absPath
|
||||
}
|
||||
}
|
||||
routeConfigDir := filepath.Dir(options.RouteConfigPath)
|
||||
if options.RouteConfigPath != "" {
|
||||
if absDir, err := filepath.Abs(routeConfigDir); err == nil {
|
||||
routeConfigDir = absDir
|
||||
}
|
||||
}
|
||||
certDir := options.CertDir
|
||||
if certDir != "" {
|
||||
if absDir, err := filepath.Abs(certDir); err == nil {
|
||||
certDir = absDir
|
||||
}
|
||||
}
|
||||
luaDir := options.LuaDir
|
||||
if luaDir != "" {
|
||||
if absDir, err := filepath.Abs(luaDir); err == nil {
|
||||
luaDir = absDir
|
||||
}
|
||||
}
|
||||
return &DockerExecutor{
|
||||
DockerBinary: options.DockerBinary,
|
||||
ContainerName: options.ContainerName,
|
||||
Image: options.Image,
|
||||
MainConfigPath: mainConfigPath,
|
||||
RouteConfigDir: routeConfigDir,
|
||||
CertDir: certDir,
|
||||
NginxCertDir: options.NginxCertDir,
|
||||
LuaDir: luaDir,
|
||||
NginxLuaDir: options.NginxLuaDir,
|
||||
OpenrestyObservabilityPort: options.OpenrestyObservabilityPort,
|
||||
Runner: runner,
|
||||
return &PathExecutor{
|
||||
Path: strings.TrimSpace(options.NginxPath),
|
||||
ConfigPath: strings.TrimSpace(options.MainConfigPath),
|
||||
Runner: runner,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,15 +370,7 @@ func detectVersion(ctx context.Context, options ExecutorOptions, runner CommandR
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
output, err := runDockerVersionProbe(ctx, runner, options.DockerBinary, options.Image)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("run docker %s -v failed: %w: %s", dockerRuntimeCommand, err, string(output))
|
||||
}
|
||||
version := parseNginxVersion(string(output))
|
||||
if version == "" {
|
||||
return "", errors.New("cannot parse runtime version from docker output")
|
||||
}
|
||||
return version, nil
|
||||
return "", errors.New("openresty path is empty")
|
||||
}
|
||||
|
||||
func parseNginxVersion(output string) string {
|
||||
@@ -682,31 +391,14 @@ func isIgnorableOpenrestyStopError(output string) bool {
|
||||
return strings.Contains(text, "invalid pid") || strings.Contains(text, "no such process")
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) runEphemeralRuntimeCommand(ctx context.Context, args ...string) ([]byte, error) {
|
||||
return e.runEphemeralRuntimeCommandWithBinary(ctx, dockerRuntimeCommand, args...)
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) runEphemeralRuntimeCommandWithBinary(ctx context.Context, runtimeBinary string, args ...string) ([]byte, error) {
|
||||
runtimeArgs := []string{
|
||||
"run",
|
||||
"--rm",
|
||||
"-v",
|
||||
fmt.Sprintf("%s:%s", e.MainConfigPath, DockerMainConfigPath),
|
||||
"-v",
|
||||
fmt.Sprintf("%s:/etc/nginx/conf.d", e.RouteConfigDir),
|
||||
"-v",
|
||||
fmt.Sprintf("%s:%s", e.CertDir, e.NginxCertDir),
|
||||
"-v",
|
||||
fmt.Sprintf("%s:%s", e.LuaDir, e.NginxLuaDir),
|
||||
e.Image,
|
||||
runtimeBinary,
|
||||
func isOpenrestyNotRunningError(output string) bool {
|
||||
text := strings.ToLower(strings.TrimSpace(output))
|
||||
if text == "" {
|
||||
return false
|
||||
}
|
||||
runtimeArgs = append(runtimeArgs, args...)
|
||||
return e.Runner.Run(ctx, e.DockerBinary, runtimeArgs...)
|
||||
}
|
||||
|
||||
func runDockerVersionProbe(ctx context.Context, runner CommandRunner, dockerBinary string, image string) ([]byte, error) {
|
||||
return runner.Run(ctx, dockerBinary, "run", "--rm", image, dockerRuntimeCommand, "-v")
|
||||
return strings.Contains(text, "invalid pid") ||
|
||||
strings.Contains(text, "no such process") ||
|
||||
strings.Contains(text, "open()") && strings.Contains(text, "nginx.pid") && strings.Contains(text, "failed")
|
||||
}
|
||||
|
||||
type backupState struct {
|
||||
@@ -737,11 +429,21 @@ func (m *Manager) backup() (*backupState, error) {
|
||||
if err := os.MkdirAll(filepath.Dir(m.RouteConfigPath), 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m.AccessLogPath != "" {
|
||||
if err := os.MkdirAll(filepath.Dir(m.AccessLogPath), 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if m.CertDir != "" {
|
||||
if err := os.MkdirAll(m.CertDir, 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if m.RuntimeConfigDir != "" {
|
||||
if err := os.MkdirAll(m.RuntimeConfigDir, 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
state := &backupState{}
|
||||
mainData, err := os.ReadFile(m.MainConfigPath)
|
||||
if err == nil {
|
||||
@@ -806,10 +508,10 @@ func (m *Manager) writeCertFiles(certFiles []protocol.SupportFile) error {
|
||||
}
|
||||
|
||||
func (m *Manager) writePowConfig(supportFiles []protocol.SupportFile) error {
|
||||
if m.LuaDir == "" {
|
||||
if m.RuntimeConfigDir == "" {
|
||||
return nil
|
||||
}
|
||||
configPath := filepath.Join(m.LuaDir, "pow_config.json")
|
||||
configPath := filepath.Join(m.RuntimeConfigDir, "pow_config.json")
|
||||
for _, file := range supportFiles {
|
||||
if file.Path == "pow_config.json" {
|
||||
if err := os.WriteFile(configPath, []byte(file.Content), 0o644); err != nil {
|
||||
@@ -822,12 +524,21 @@ func (m *Manager) writePowConfig(supportFiles []protocol.SupportFile) error {
|
||||
if err := os.Remove(configPath); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove pow_config.json: %w", err)
|
||||
}
|
||||
if err := removeLegacyPowConfig(filepath.Join(m.LuaDir, "pow_config.json")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := removeLegacyPowConfig(filepath.Join(m.CertDir, "pow_config.json")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) writeManagedCertFiles(certFiles []protocol.SupportFile) error {
|
||||
files := make([]managedFile, 0, len(certFiles))
|
||||
for _, file := range certFiles {
|
||||
if file.Path == "pow_config.json" {
|
||||
continue
|
||||
}
|
||||
targetPath, err := m.certFileTargetPath(file.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -863,11 +574,14 @@ func (m *Manager) readCertFiles() ([]protocol.SupportFile, error) {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
relativePath, err := filepath.Rel(m.CertDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
relativePath, err := filepath.Rel(m.CertDir, path)
|
||||
if filepath.ToSlash(relativePath) == "pow_config.json" {
|
||||
return nil
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -887,10 +601,10 @@ func (m *Manager) readCertFiles() ([]protocol.SupportFile, error) {
|
||||
}
|
||||
|
||||
func (m *Manager) readPowConfigFile() (*protocol.SupportFile, error) {
|
||||
if m.LuaDir == "" {
|
||||
if m.RuntimeConfigDir == "" {
|
||||
return nil, nil
|
||||
}
|
||||
configPath := filepath.Join(m.LuaDir, "pow_config.json")
|
||||
configPath := filepath.Join(m.RuntimeConfigDir, "pow_config.json")
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -920,10 +634,10 @@ func (m *Manager) readManagedSupportFiles() ([]protocol.SupportFile, error) {
|
||||
}
|
||||
|
||||
func (m *Manager) restorePowConfig(state *backupState) error {
|
||||
if state == nil || m.LuaDir == "" {
|
||||
if state == nil || m.RuntimeConfigDir == "" {
|
||||
return nil
|
||||
}
|
||||
configPath := filepath.Join(m.LuaDir, "pow_config.json")
|
||||
configPath := filepath.Join(m.RuntimeConfigDir, "pow_config.json")
|
||||
if state.PowConfig == nil {
|
||||
if err := os.Remove(configPath); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
@@ -933,6 +647,16 @@ func (m *Manager) restorePowConfig(state *backupState) error {
|
||||
return os.WriteFile(configPath, []byte(state.PowConfig.Content), 0o644)
|
||||
}
|
||||
|
||||
func removeLegacyPowConfig(path string) error {
|
||||
if strings.TrimSpace(path) == "" {
|
||||
return nil
|
||||
}
|
||||
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("remove legacy pow_config.json %q: %w", path, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) certFileTargetPath(relativePath string) (string, error) {
|
||||
if strings.TrimSpace(m.CertDir) == "" {
|
||||
return "", errors.New("cert dir 不能为空")
|
||||
@@ -1119,14 +843,20 @@ func (m *Manager) renderMainConfig(content string) string {
|
||||
return rendered
|
||||
}
|
||||
|
||||
func (m *Manager) managedPowLuaFiles() []protocol.SupportFile {
|
||||
files := ManagedPowLuaFiles()
|
||||
runtimeConfigDir := filepath.ToSlash(strings.TrimSpace(m.RuntimeConfigDir))
|
||||
for index := range files {
|
||||
files[index].Content = strings.ReplaceAll(files[index].Content, RuntimeConfigDirPlaceholder, runtimeConfigDir)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
func ObservabilityListenAddress(openrestyPath string, port int) string {
|
||||
if port <= 0 {
|
||||
return ""
|
||||
}
|
||||
if strings.TrimSpace(openrestyPath) != "" {
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
return fmt.Sprintf("%d", port)
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
|
||||
func ResolverDirective(openrestyPath string, explicitResolvers []string) string {
|
||||
@@ -1145,7 +875,7 @@ func resolverAddresses(openrestyPath string, explicitResolvers []string) []strin
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parseResolverAddresses(string(data), strings.TrimSpace(openrestyPath) == "")
|
||||
return parseResolverAddresses(string(data), false)
|
||||
}
|
||||
|
||||
func parseResolverAddresses(content string, dockerMode bool) []string {
|
||||
@@ -1213,18 +943,11 @@ func RequiresRuntimeResolver(originURL string) bool {
|
||||
}
|
||||
|
||||
func (m *Manager) routeConfigIncludePath() string {
|
||||
if strings.TrimSpace(m.RuntimeRouteConfigPath) != "" {
|
||||
return strings.TrimSpace(m.RuntimeRouteConfigPath)
|
||||
}
|
||||
return strings.TrimSpace(m.RouteConfigPath)
|
||||
}
|
||||
|
||||
func (m *Manager) accessLogRuntimePath() string {
|
||||
includePath := m.routeConfigIncludePath()
|
||||
if strings.TrimSpace(includePath) == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.ToSlash(filepath.Join(filepath.Dir(includePath), "openflare_access.log"))
|
||||
return filepath.ToSlash(strings.TrimSpace(m.AccessLogPath))
|
||||
}
|
||||
|
||||
func (m *Manager) luaRuntimePath() string {
|
||||
|
||||
Reference in New Issue
Block a user