Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6d552f944
|
@@ -45,10 +45,7 @@ jobs:
|
|||||||
make lint-database-integration
|
make lint-database-integration
|
||||||
|
|
||||||
database-integration:
|
database-integration:
|
||||||
runs-on: [self-hosted, pod]
|
runs-on: [self-hosted, vm]
|
||||||
timeout-minutes: 30
|
|
||||||
env:
|
|
||||||
DOCKER_HOST: unix:///var/run/docker.sock
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||||
@@ -61,27 +58,5 @@ jobs:
|
|||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
# 复用 dynamic runner 的 pod-smoke:daemon 与数据只属于本次 Pod job。
|
- name: Test Database credentials with real backends
|
||||||
- name: Start job-local Docker
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
command -v docker
|
|
||||||
command -v dockerd
|
|
||||||
findmnt /var/lib/docker
|
|
||||||
sudo -n nohup dockerd \
|
|
||||||
--host=unix:///var/run/docker.sock \
|
|
||||||
--storage-driver=overlay2 \
|
|
||||||
>/tmp/ayatori-dockerd.log 2>&1 &
|
|
||||||
for _ in {1..60}; do
|
|
||||||
if docker info >/dev/null 2>&1; then
|
|
||||||
docker version
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
cat /tmp/ayatori-dockerd.log
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Test Database integration with real backends
|
|
||||||
run: make test-database-integration
|
run: make test-database-integration
|
||||||
|
|||||||
@@ -53,8 +53,7 @@ controller 接入、Secret watch、finalizer、registry 观测装配与真实权
|
|||||||
运行 `make test-database-integration` 验证真实 API server + 一次性 PostgreSQL;fixture 不接受外部
|
运行 `make test-database-integration` 验证真实 API server + 一次性 PostgreSQL;fixture 不接受外部
|
||||||
DSN,镜像固定摘要,使用随机本机回环端口并在退出时删除测试容器。覆盖缺失/错误凭据、RBAC、
|
DSN,镜像固定摘要,使用随机本机回环端口并在退出时删除测试容器。覆盖缺失/错误凭据、RBAC、
|
||||||
namespace 边界、有效值轮换、metadata 无关变化、中途轮换、重建/重试、并发读取、Forget/Close
|
namespace 边界、有效值轮换、metadata 无关变化、中途轮换、重建/重试、并发读取、Forget/Close
|
||||||
与 TLS DNS/IP SAN、错误 CA/主机名和禁止明文降级。CI 使用 Pod runner 执行,workflow 显式启动
|
与 TLS DNS/IP SAN、错误 CA/主机名和禁止明文降级。CI 使用 VM runner 执行,普通 lint 之外还检查
|
||||||
本 job 独占的 Docker daemon,随 Pod 销毁;不依赖 VM 或共享宿主 Docker。普通 lint 之外还检查
|
|
||||||
integration 标签代码。领域单测、真实 API 行为与真实 PostgreSQL 行为分别验收,不以本切片
|
integration 标签代码。领域单测、真实 API 行为与真实 PostgreSQL 行为分别验收,不以本切片
|
||||||
替代整个 Instance controller 的集成验收。
|
替代整个 Instance controller 的集成验收。
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ TLS 测试在临时目录生成一次性证书与私钥,不使用生产 CA。
|
|||||||
|
|
||||||
当前覆盖固定 namespace 的 Secret 读取与 RBAC、缺失/无效凭据恢复、有效凭据变化后的重连、
|
当前覆盖固定 namespace 的 Secret 读取与 RBAC、缺失/无效凭据恢复、有效凭据变化后的重连、
|
||||||
无关字段更新不重连、中途轮换时丢弃观察、会话重建、并发读取、本地连接释放和 TLS 验证。
|
无关字段更新不重连、中途轮换时丢弃观察、会话重建、并发读取、本地连接释放和 TLS 验证。
|
||||||
快速测试、lint 和 Database 集成测试均使用 Pod runner。集成 job 按 dynamic runner 的
|
默认 Pod runner 跑快速测试与 lint,VM runner 跑带 Docker 的 Database 集成测试。
|
||||||
`pod-smoke.yml` 显式启动 Pod 内独占的 Docker daemon(overlay2),预检成功后再运行测试,
|
|
||||||
不依赖 VM、共享宿主 Docker 或生产数据库。daemon 与数据随 job Pod 销毁。
|
|
||||||
daemon 启动失败会打印启动日志;fixture 启动失败会保留退出错误与 stderr,并遮蔽测试密码,
|
|
||||||
以区分缺少命令、daemon 不可达、权限和镜像拉取失败。
|
|
||||||
|
|
||||||
registry 测试独立使用一次性 PostgreSQL,不启动 Kubernetes API server。覆盖重复和并发迁移、
|
registry 测试独立使用一次性 PostgreSQL,不启动 Kubernetes API server。覆盖重复和并发迁移、
|
||||||
所有权唯一约束、并发占用、Retain 墓碑与 Delete 幂等、连接重建、取消恢复、未知 schema 与
|
所有权唯一约束、并发占用、Retain 墓碑与 Delete 幂等、连接重建、取消恢复、未知 schema 与
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package postgresql_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -56,7 +55,7 @@ func postgresFixture(t *testing.T, ctx context.Context) (string, int) {
|
|||||||
output, err := exec.CommandContext(ctx, "docker", "run", "--rm", "-d", "-p", "127.0.0.1::5432",
|
output, err := exec.CommandContext(ctx, "docker", "run", "--rm", "-d", "-p", "127.0.0.1::5432",
|
||||||
"-e", "POSTGRES_PASSWORD="+fixturePassword, fixtureImage).Output()
|
"-e", "POSTGRES_PASSWORD="+fixturePassword, fixtureImage).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("cannot start isolated PostgreSQL fixture: %s", fixtureCommandError(err))
|
t.Fatal("cannot start isolated PostgreSQL fixture")
|
||||||
}
|
}
|
||||||
id := strings.TrimSpace(string(output))
|
id := strings.TrimSpace(string(output))
|
||||||
if !regexp.MustCompile(`^[a-f0-9]{64}$`).MatchString(id) {
|
if !regexp.MustCompile(`^[a-f0-9]{64}$`).MatchString(id) {
|
||||||
@@ -71,7 +70,7 @@ func postgresFixture(t *testing.T, ctx context.Context) (string, int) {
|
|||||||
})
|
})
|
||||||
output, err = exec.CommandContext(ctx, "docker", "inspect", "--format", `{{(index (index .NetworkSettings.Ports "5432/tcp") 0).HostPort}}`, id).Output()
|
output, err = exec.CommandContext(ctx, "docker", "inspect", "--format", `{{(index (index .NetworkSettings.Ports "5432/tcp") 0).HostPort}}`, id).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("cannot inspect fixture port: %s", fixtureCommandError(err))
|
t.Fatal("cannot inspect fixture port")
|
||||||
}
|
}
|
||||||
port, err := strconv.Atoi(strings.TrimSpace(string(output)))
|
port, err := strconv.Atoi(strings.TrimSpace(string(output)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,59 +87,6 @@ func postgresFixture(t *testing.T, ctx context.Context) (string, int) {
|
|||||||
return id, port
|
return id, port
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output 将 stderr 保存在 ExitError 中;保留诊断,但不打印命令参数和测试密码。
|
|
||||||
func fixtureCommandError(err error) string {
|
|
||||||
detail := err.Error()
|
|
||||||
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
|
|
||||||
detail += ": " + strings.TrimSpace(string(exitErr.Stderr))
|
|
||||||
}
|
|
||||||
redactor := strings.NewReplacer(
|
|
||||||
fixturePassword, "[REDACTED]",
|
|
||||||
rotatedPassword, "[REDACTED]",
|
|
||||||
)
|
|
||||||
return redactor.Replace(detail)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFixtureCommandErrorPreservesDiagnosticsAndRedactsPasswords(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
err error
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "missing docker executable",
|
|
||||||
err: &exec.Error{Name: "docker", Err: exec.ErrNotFound},
|
|
||||||
want: "executable file not found",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "daemon failure from stderr",
|
|
||||||
err: &exec.ExitError{Stderr: []byte("Cannot connect to the Docker daemon")},
|
|
||||||
want: "Cannot connect to the Docker daemon",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "passwords in stderr",
|
|
||||||
err: &exec.ExitError{Stderr: []byte("failure: " + fixturePassword + " " + rotatedPassword)},
|
|
||||||
want: "failure: [REDACTED] [REDACTED]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "password in error text",
|
|
||||||
err: errors.New("failure: " + fixturePassword),
|
|
||||||
want: "failure: [REDACTED]",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
detail := fixtureCommandError(tt.err)
|
|
||||||
if !strings.Contains(detail, tt.want) {
|
|
||||||
t.Fatalf("diagnostic lost expected information: %q", tt.want)
|
|
||||||
}
|
|
||||||
if strings.Contains(detail, fixturePassword) || strings.Contains(detail, rotatedPassword) {
|
|
||||||
t.Fatal("diagnostic exposed a fixture password")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func target(t *testing.T, port int, mode instance.TLSMode) instance.ObservationTarget {
|
func target(t *testing.T, port int, mode instance.TLSMode) instance.ObservationTarget {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
id, err := instance.NewIdentity("fixture-uid", "fixture")
|
id, err := instance.NewIdentity("fixture-uid", "fixture")
|
||||||
|
|||||||
Reference in New Issue
Block a user