refactor: use nginx -s reload instead of systemd

- doc: add comment
This commit is contained in:
2026-08-17 10:10:14 +08:00
parent 79f18fcdea
commit f536987a7e
62 changed files with 2216 additions and 598 deletions
+50 -6
View File
@@ -19,11 +19,16 @@ import (
)
const (
testDigest = "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
testRepository = "harbor.ymswell.asia/ymswell/glory-ymswell"
// testDigest 测试中使用的固定镜像清单摘要。
testDigest = "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
// testRepository 测试中使用的镜像仓库前缀。
testRepository = "harbor.ymswell.asia/ymswell/glory-ymswell"
// healthyResponse 测试中健康检查端点返回的固定 UP 响应体。
healthyResponse = `{"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"},"ping":{"status":"UP"},"redis":{"status":"UP"}}}`
)
// TestExecutorPreservesOpaqueImageTagsAndReachesSwitching 验证执行器对不透明镜像标签保持原样传递,
// 并能使事务推进到 StateSwitching;同时验证在 StateSwitching 状态重复执行不会产生额外引擎调用。
func TestExecutorPreservesOpaqueImageTagsAndReachesSwitching(t *testing.T) {
tags := []string{
"20260814-093609-d7ed70f0-v1.1.8.1",
@@ -80,6 +85,8 @@ func TestExecutorPreservesOpaqueImageTagsAndReachesSwitching(t *testing.T) {
}
}
// TestExecutorRecoversRecordedCreateIntentWithoutRepeatingCreate 验证在 crash 窗口内已记录创建步骤意图后,
// 恢复执行不会重复创建容器,而是直接复用已完成的创建步骤并最终进入 StateSwitching。
func TestExecutorRecoversRecordedCreateIntentWithoutRepeatingCreate(t *testing.T) {
ctx := context.Background()
store, coordinator := testTransactionKernel(t)
@@ -125,6 +132,7 @@ func TestExecutorRecoversRecordedCreateIntentWithoutRepeatingCreate(t *testing.T
}
}
// TestExecutorMarksValidationFailureTerminal 验证请求校验失败时事务被置为 StateFailed 终态。
func TestExecutorMarksValidationFailureTerminal(t *testing.T) {
ctx := context.Background()
store, coordinator := testTransactionKernel(t)
@@ -143,6 +151,8 @@ func TestExecutorMarksValidationFailureTerminal(t *testing.T) {
}
}
// TestExecutorReplacesInactiveContainerWithConflictingImage 验证当存在镜像标识冲突的非活动容器时,
// 执行器会移除该容器并重新创建,最终进入 StateSwitching。
func TestExecutorReplacesInactiveContainerWithConflictingImage(t *testing.T) {
ctx := context.Background()
store, coordinator := testTransactionKernel(t)
@@ -170,6 +180,8 @@ func TestExecutorReplacesInactiveContainerWithConflictingImage(t *testing.T) {
}
}
// TestExecutorRejectsChangedRecoveryRequestWithoutChangingState 验证恢复执行时若请求参数被改动,
// 执行器会因持久化意图冲突而拒绝,且不改变事务的 StateStarting 状态。
func TestExecutorRejectsChangedRecoveryRequestWithoutChangingState(t *testing.T) {
ctx := context.Background()
store, coordinator := testTransactionKernel(t)
@@ -198,6 +210,8 @@ func TestExecutorRejectsChangedRecoveryRequestWithoutChangingState(t *testing.T)
}
}
// TestImageMatchesRequiresDigestEvidenceAndExactPlatform 验证镜像匹配逻辑要求存在摘要证据且平台完全一致,
// 镜像 ID 单独存在不足以满足清单摘要匹配,平台不一致时不得判定匹配。
func TestImageMatchesRequiresDigestEvidenceAndExactPlatform(t *testing.T) {
t.Parallel()
platform := containerengine.Platform{OS: "linux", Architecture: "arm64"}
@@ -222,6 +236,7 @@ func TestImageMatchesRequiresDigestEvidenceAndExactPlatform(t *testing.T) {
}
}
// testRequest 构造一个合法的测试请求,并在临时目录中写入镜像归档与后端配置文件。
func testRequest(t *testing.T, imageReference string) Request {
t.Helper()
directory := t.TempDir()
@@ -253,6 +268,7 @@ func testRequest(t *testing.T, imageReference string) Request {
}
}
// testTransactionKernel 创建测试用的事务存储与协调器,并在测试结束时自动关闭存储。
func testTransactionKernel(t *testing.T) (*transaction.Store, *transaction.Coordinator) {
t.Helper()
store, err := transaction.OpenStore(context.Background(), filepath.Join(t.TempDir(), "transactions.db"))
@@ -267,6 +283,7 @@ func testTransactionKernel(t *testing.T) (*transaction.Store, *transaction.Coord
return store, coordinator
}
// testExecutor 使用固定响应体构造健康检查 HTTP 客户端并创建后端执行器。
func testExecutor(t *testing.T, store *transaction.Store, coordinator *transaction.Coordinator, engine containerengine.Engine, body string) *Executor {
t.Helper()
client := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) {
@@ -279,6 +296,7 @@ func testExecutor(t *testing.T, store *transaction.Store, coordinator *transacti
return executor
}
// createTransaction 以给定后缀创建一个新的后端测试事务并返回其记录。
func createTransaction(t *testing.T, store *transaction.Store, suffix string) transaction.Transaction {
t.Helper()
record, _, err := store.CreateTransaction(context.Background(), transaction.CreateRequest{
@@ -293,6 +311,7 @@ func createTransaction(t *testing.T, store *transaction.Store, suffix string) tr
return record
}
// transitionToPrepared 将指定事务依次推进到 StateValidating 与 StatePrepared 状态。
func transitionToPrepared(t *testing.T, store *transaction.Store, transactionID string) {
t.Helper()
ctx := context.Background()
@@ -304,12 +323,15 @@ func transitionToPrepared(t *testing.T, store *transaction.Store, transactionID
}
}
// roundTripFunc http.RoundTripper 的函数式适配器,用于在测试中固定 HTTP 响应。
type roundTripFunc func(*http.Request) (*http.Response, error)
// RoundTrip 实现 http.RoundTripper 接口,直接调用底层函数。
func (f roundTripFunc) RoundTrip(request *http.Request) (*http.Response, error) {
return f(request)
}
// engineCalls 记录 fakeEngine 各方法被调用的次数,用于断言执行路径。
type engineCalls struct {
ping int
load int
@@ -319,12 +341,19 @@ type engineCalls struct {
remove int
}
// fakeEngine containerengine.Engine 的内存实现,用于测试中模拟容器引擎行为。
type fakeEngine struct {
mu sync.Mutex
request Request
loadedImage containerengine.Image
// mu 保护下方字段的并发访问。
mu sync.Mutex
// request 构造该引擎时使用的请求参数。
request Request
// loadedImage 引擎加载后提供的镜像。
loadedImage containerengine.Image
// imageAvailable 表示镜像当前是否可用。
imageAvailable bool
containers map[string]containerengine.Container
// containers 引擎维护的容器表,键为容器名称。
containers map[string]containerengine.Container
// lastCreateSpec 记录最近一次创建容器所用的规格。
lastCreateSpec containerengine.ContainerSpec
pingCalls int
loadCalls int
@@ -334,6 +363,7 @@ type fakeEngine struct {
removeCalls int
}
// newFakeEngine 构造一个已按请求平台预置镜像的 fakeEngine。
func newFakeEngine(request Request) *fakeEngine {
return &fakeEngine{
request: request,
@@ -346,6 +376,7 @@ func newFakeEngine(request Request) *fakeEngine {
}
}
// Ping 实现容器引擎的 Ping,记录调用次数并始终返回成功。
func (e *fakeEngine) Ping(context.Context) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -353,6 +384,7 @@ func (e *fakeEngine) Ping(context.Context) error {
return nil
}
// LoadImage 实现容器引擎的 LoadImage,读取输入流后标记镜像可用并记录调用次数。
func (e *fakeEngine) LoadImage(_ context.Context, input io.Reader) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -364,6 +396,7 @@ func (e *fakeEngine) LoadImage(_ context.Context, input io.Reader) error {
return nil
}
// PullImage 实现容器引擎的 PullImage,标记镜像可用并记录调用次数。
func (e *fakeEngine) PullImage(context.Context, string) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -372,6 +405,7 @@ func (e *fakeEngine) PullImage(context.Context, string) error {
return nil
}
// InspectImage 实现容器引擎的 InspectImage,镜像不可用时返回 ErrNotFound,否则返回已加载镜像。
func (e *fakeEngine) InspectImage(context.Context, string) (containerengine.Image, error) {
e.mu.Lock()
defer e.mu.Unlock()
@@ -382,6 +416,7 @@ func (e *fakeEngine) InspectImage(context.Context, string) (containerengine.Imag
return e.loadedImage, nil
}
// CreateContainer 实现容器引擎的 CreateContainer,记录规格并创建容器,同名时返回错误。
func (e *fakeEngine) CreateContainer(_ context.Context, spec containerengine.ContainerSpec) (containerengine.Container, error) {
e.mu.Lock()
defer e.mu.Unlock()
@@ -395,6 +430,7 @@ func (e *fakeEngine) CreateContainer(_ context.Context, spec containerengine.Con
return record, nil
}
// StartContainer 实现容器引擎的 StartContainer,将指定容器标记为运行状态,不存在时返回 ErrNotFound。
func (e *fakeEngine) StartContainer(_ context.Context, name string) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -409,10 +445,12 @@ func (e *fakeEngine) StartContainer(_ context.Context, name string) error {
return nil
}
// ContainerLogs 实现容器引擎的 ContainerLogs,返回空的日志读取器。
func (e *fakeEngine) ContainerLogs(context.Context, string) (io.ReadCloser, error) {
return io.NopCloser(strings.NewReader("")), nil
}
// StopContainer 实现容器引擎的 StopContainer,将指定容器标记为已退出状态,不存在时返回 ErrNotFound。
func (e *fakeEngine) StopContainer(_ context.Context, name string) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -426,6 +464,7 @@ func (e *fakeEngine) StopContainer(_ context.Context, name string) error {
return nil
}
// InspectContainer 实现容器引擎的 InspectContainer,返回容器记录,不存在时返回 ErrNotFound。
func (e *fakeEngine) InspectContainer(_ context.Context, name string) (containerengine.Container, error) {
e.mu.Lock()
defer e.mu.Unlock()
@@ -436,6 +475,7 @@ func (e *fakeEngine) InspectContainer(_ context.Context, name string) (container
return record, nil
}
// RemoveContainer 实现容器引擎的 RemoveContainer,删除指定容器并记录调用次数,不存在时返回 ErrNotFound。
func (e *fakeEngine) RemoveContainer(_ context.Context, name string, _ bool) error {
e.mu.Lock()
defer e.mu.Unlock()
@@ -447,8 +487,10 @@ func (e *fakeEngine) RemoveContainer(_ context.Context, name string, _ bool) err
return nil
}
// Close 实现容器引擎的 Close,不做任何清理并返回 nil。
func (e *fakeEngine) Close() error { return nil }
// containerFromSpec 根据容器规格构造一条容器记录,running 指定其初始运行状态。
func (e *fakeEngine) containerFromSpec(spec containerengine.ContainerSpec, running bool) containerengine.Container {
return containerengine.Container{
ID: "container-id-" + spec.Name,
@@ -467,6 +509,7 @@ func (e *fakeEngine) containerFromSpec(spec containerengine.ContainerSpec, runni
}
}
// callCounts 返回 fakeEngine 各方法当前的调用次数快照。
func (e *fakeEngine) callCounts() engineCalls {
return engineCalls{
ping: e.pingCalls,
@@ -478,4 +521,5 @@ func (e *fakeEngine) callCounts() engineCalls {
}
}
// 编译期断言确保 fakeEngine 实现 containerengine.Engine 接口。
var _ containerengine.Engine = (*fakeEngine)(nil)