mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
[优化] 更新 openresty_observability_port 描述,增强健康检查逻辑,使用 stub_status 代替 openresty -t
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"openflare-agent/internal/protocol"
|
||||
)
|
||||
@@ -171,9 +173,22 @@ http {
|
||||
server_name _;
|
||||
return 503 "OpenFlare: No Valid Configuration\n";
|
||||
}
|
||||
%s
|
||||
}
|
||||
`
|
||||
|
||||
const safeDefaultFallbackObservabilityServerBlock = `
|
||||
server {
|
||||
listen %s;
|
||||
server_name openflare-observability;
|
||||
access_log off;
|
||||
|
||||
location = /openflare/stub_status {
|
||||
stub_status;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
type ApplyOutcome struct {
|
||||
Status ApplyStatus
|
||||
Message string
|
||||
@@ -334,7 +349,10 @@ func (m *Manager) CheckHealth(ctx context.Context) error {
|
||||
return errors.New("openresty config not exists: waiting for initial sync")
|
||||
}
|
||||
}
|
||||
return m.Executor.CheckHealth(ctx)
|
||||
if m.OpenrestyObservabilityPort <= 0 {
|
||||
return m.Executor.CheckHealth(ctx)
|
||||
}
|
||||
return m.checkStubStatus(ctx)
|
||||
}
|
||||
|
||||
func (m *Manager) Restart(ctx context.Context) error {
|
||||
@@ -740,12 +758,39 @@ func (m *Manager) writeSafeDefaultFallbackFiles() error {
|
||||
if err := os.WriteFile(m.RouteConfigPath, nil, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(m.MainConfigPath, []byte(safeDefaultFallbackMainConfig), 0o644); err != nil {
|
||||
if err := os.WriteFile(m.MainConfigPath, []byte(m.safeDefaultFallbackMainConfig()), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) safeDefaultFallbackMainConfig() string {
|
||||
observabilityBlock := ""
|
||||
if listen := strings.TrimSpace(m.OpenrestyObservabilityListen); listen != "" {
|
||||
observabilityBlock = fmt.Sprintf(safeDefaultFallbackObservabilityServerBlock, listen)
|
||||
}
|
||||
return fmt.Sprintf(safeDefaultFallbackMainConfig, observabilityBlock)
|
||||
}
|
||||
|
||||
func (m *Manager) checkStubStatus(ctx context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, 1500*time.Millisecond)
|
||||
defer cancel()
|
||||
openrestyStubUrl := fmt.Sprintf("http://127.0.0.1:%d/openflare/stub_status", m.OpenrestyObservabilityPort)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, openrestyStubUrl, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := (&http.Client{}).Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("openresty health endpoint unreachable: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("openresty health endpoint returned %s", resp.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeLegacyPowConfig(path string) error {
|
||||
if strings.TrimSpace(path) == "" {
|
||||
return nil
|
||||
|
||||
@@ -3,6 +3,8 @@ package nginx
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@@ -328,6 +330,67 @@ func TestManagerApplyWritesSupportFilesAndReplacesPlaceholder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagerCheckHealthUsesStubStatusInsteadOfConfigTest(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Listen failed: %v", err)
|
||||
}
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
server := &http.Server{
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/openflare/stub_status" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("Active connections: 1\n"))
|
||||
}),
|
||||
}
|
||||
go func() {
|
||||
_ = server.Serve(listener)
|
||||
}()
|
||||
defer server.Shutdown(context.Background())
|
||||
|
||||
mainPath := filepath.Join(t.TempDir(), "nginx.conf")
|
||||
if err := os.WriteFile(mainPath, []byte("main"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile failed: %v", err)
|
||||
}
|
||||
manager := &Manager{
|
||||
MainConfigPath: mainPath,
|
||||
OpenrestyObservabilityPort: port,
|
||||
Executor: &fakeExecutor{
|
||||
testErr: errors.New("openresty -t should not be called"),
|
||||
},
|
||||
}
|
||||
if err := manager.CheckHealth(context.Background()); err != nil {
|
||||
t.Fatalf("CheckHealth failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagerCheckHealthFailsWhenStubStatusUnavailable(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Listen failed: %v", err)
|
||||
}
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
if err := listener.Close(); err != nil {
|
||||
t.Fatalf("listener close failed: %v", err)
|
||||
}
|
||||
|
||||
mainPath := filepath.Join(t.TempDir(), "nginx.conf")
|
||||
if err := os.WriteFile(mainPath, []byte("main"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile failed: %v", err)
|
||||
}
|
||||
manager := &Manager{
|
||||
MainConfigPath: mainPath,
|
||||
OpenrestyObservabilityPort: port,
|
||||
Executor: &fakeExecutor{},
|
||||
}
|
||||
if err := manager.CheckHealth(context.Background()); err == nil {
|
||||
t.Fatal("expected CheckHealth to fail when stub_status is unavailable")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolverDirectiveUsesExplicitResolvers(t *testing.T) {
|
||||
got := ResolverDirective("", []string{"10.0.0.2", "1.1.1.1"})
|
||||
if !strings.Contains(got, "resolver 10.0.0.2 1.1.1.1") {
|
||||
@@ -748,9 +811,10 @@ func TestManagerApplyStartsSafeFallbackWhenNoRollbackConfigExists(t *testing.T)
|
||||
testErrors: []error{errors.New("target config failed"), errors.New("rollback config missing"), nil},
|
||||
}
|
||||
manager := &Manager{
|
||||
MainConfigPath: mainPath,
|
||||
RouteConfigPath: routePath,
|
||||
Executor: executor,
|
||||
MainConfigPath: mainPath,
|
||||
RouteConfigPath: routePath,
|
||||
OpenrestyObservabilityListen: "127.0.0.1:18081",
|
||||
Executor: executor,
|
||||
}
|
||||
|
||||
outcome := manager.Apply(context.Background(), "bad-main", "bad-route", nil)
|
||||
@@ -773,6 +837,12 @@ func TestManagerApplyStartsSafeFallbackWhenNoRollbackConfigExists(t *testing.T)
|
||||
if !strings.Contains(string(mainData), "listen 80 default_server") {
|
||||
t.Fatalf("expected fallback to listen on port 80, got %s", string(mainData))
|
||||
}
|
||||
if !strings.Contains(string(mainData), "listen 127.0.0.1:18081") {
|
||||
t.Fatalf("expected fallback to expose local stub_status port, got %s", string(mainData))
|
||||
}
|
||||
if !strings.Contains(string(mainData), "stub_status;") {
|
||||
t.Fatalf("expected fallback to expose stub_status, got %s", string(mainData))
|
||||
}
|
||||
routeData, err := os.ReadFile(routePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read route config: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user