mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 00:26:37 +08:00
重构 Nginx 执行器,支持通过 Docker 启动独立 Nginx 容器,更新配置结构,完善相关文档和测试用例
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Executor interface {
|
||||
@@ -14,28 +15,97 @@ type Executor interface {
|
||||
Reload(ctx context.Context) error
|
||||
}
|
||||
|
||||
type ShellExecutor struct {
|
||||
Binary string
|
||||
type CommandRunner interface {
|
||||
Run(ctx context.Context, name string, args ...string) ([]byte, error)
|
||||
}
|
||||
|
||||
func (e *ShellExecutor) Test(ctx context.Context) error {
|
||||
cmd := exec.CommandContext(ctx, e.Binary, "-t")
|
||||
type OSCommandRunner struct{}
|
||||
|
||||
func (r *OSCommandRunner) Run(ctx context.Context, name string, args ...string) ([]byte, error) {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
return output, err
|
||||
}
|
||||
|
||||
type PathExecutor struct {
|
||||
Path string
|
||||
Runner CommandRunner
|
||||
}
|
||||
|
||||
func (e *PathExecutor) Test(ctx context.Context) error {
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-t")
|
||||
if err != nil {
|
||||
return fmt.Errorf("nginx -t failed: %w: %s", err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ShellExecutor) Reload(ctx context.Context) error {
|
||||
cmd := exec.CommandContext(ctx, e.Binary, "-s", "reload")
|
||||
output, err := cmd.CombinedOutput()
|
||||
func (e *PathExecutor) Reload(ctx context.Context) error {
|
||||
output, err := e.Runner.Run(ctx, e.Path, "-s", "reload")
|
||||
if err != nil {
|
||||
return fmt.Errorf("nginx reload failed: %w: %s", err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DockerExecutor struct {
|
||||
DockerBinary string
|
||||
ContainerName string
|
||||
Image string
|
||||
RouteConfigDir string
|
||||
Runner CommandRunner
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) Test(ctx context.Context) error {
|
||||
if err := e.ensureContainer(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "exec", e.ContainerName, "nginx", "-t")
|
||||
if err != nil {
|
||||
return fmt.Errorf("docker nginx -t failed: %w: %s", err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) Reload(ctx context.Context) error {
|
||||
if err := e.ensureContainer(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "exec", e.ContainerName, "nginx", "-s", "reload")
|
||||
if err != nil {
|
||||
return fmt.Errorf("docker nginx reload failed: %w: %s", err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *DockerExecutor) ensureContainer(ctx context.Context) error {
|
||||
output, err := e.Runner.Run(ctx, e.DockerBinary, "inspect", "-f", "{{.State.Running}}", e.ContainerName)
|
||||
if err == nil {
|
||||
if strings.TrimSpace(string(output)) == "true" {
|
||||
return nil
|
||||
}
|
||||
startOutput, startErr := e.Runner.Run(ctx, e.DockerBinary, "start", e.ContainerName)
|
||||
if startErr != nil {
|
||||
return fmt.Errorf("docker start nginx failed: %w: %s", startErr, string(startOutput))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
runArgs := []string{
|
||||
"run", "-d",
|
||||
"--name", e.ContainerName,
|
||||
"-p", "80:80",
|
||||
"-p", "443:443",
|
||||
"-v", fmt.Sprintf("%s:/etc/nginx/conf.d", e.RouteConfigDir),
|
||||
e.Image,
|
||||
}
|
||||
runOutput, runErr := e.Runner.Run(ctx, e.DockerBinary, runArgs...)
|
||||
if runErr != nil {
|
||||
return fmt.Errorf("docker run nginx failed: %w: %s", runErr, string(runOutput))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
RouteConfigPath string
|
||||
Executor Executor
|
||||
@@ -63,6 +133,31 @@ func (m *Manager) Apply(ctx context.Context, content string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExecutorOptions struct {
|
||||
NginxPath string
|
||||
DockerBinary string
|
||||
ContainerName string
|
||||
Image string
|
||||
RouteConfigPath string
|
||||
}
|
||||
|
||||
func NewExecutor(options ExecutorOptions) Executor {
|
||||
runner := &OSCommandRunner{}
|
||||
if options.NginxPath != "" {
|
||||
return &PathExecutor{
|
||||
Path: options.NginxPath,
|
||||
Runner: runner,
|
||||
}
|
||||
}
|
||||
return &DockerExecutor{
|
||||
DockerBinary: options.DockerBinary,
|
||||
ContainerName: options.ContainerName,
|
||||
Image: options.Image,
|
||||
RouteConfigDir: filepath.Dir(options.RouteConfigPath),
|
||||
Runner: runner,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) backup() (string, bool, error) {
|
||||
if m.RouteConfigPath == "" {
|
||||
return "", false, errors.New("route config path 不能为空")
|
||||
|
||||
Reference in New Issue
Block a user