diff --git a/config/platform-db/postgres-pk01.yaml b/config/platform-db/postgres-pk01.yaml index 8795f1c6..276cf0bd 100644 --- a/config/platform-db/postgres-pk01.yaml +++ b/config/platform-db/postgres-pk01.yaml @@ -10,6 +10,7 @@ metadata: - 281 - 297 - 300 + - 2078 cluster: role: primary @@ -374,6 +375,16 @@ postgres: user: pikaoa address: 152.53.229.148/32 method: scram-sha-256 + - type: hostssl + database: pikaoa_test + user: pikaoa_test + address: 10.0.8.0/22 + method: scram-sha-256 + - type: hostssl + database: pikaoa_test + user: pikaoa_test + address: 152.53.229.148/32 + method: scram-sha-256 secrets: source: master-local @@ -491,6 +502,20 @@ secrets: PIKAOA_DB_NAME: pikaoa randomHex: PIKAOA_DB_PASSWORD: 32 + - name: pikaoa-test-db-credentials + sourceRef: platform-db/pikaoa-test-db.env + type: env + requiredKeys: + - PIKAOA_TEST_DB_USER + - PIKAOA_TEST_DB_PASSWORD + - PIKAOA_TEST_DB_NAME + createIfMissing: + enabled: true + values: + PIKAOA_TEST_DB_USER: pikaoa_test + PIKAOA_TEST_DB_NAME: pikaoa_test + randomHex: + PIKAOA_TEST_DB_PASSWORD: 32 objects: roles: - name: sub2api @@ -565,6 +590,15 @@ objects: createdb: false createrole: false superuser: false + - name: pikaoa_test + passwordRef: + sourceRef: platform-db/pikaoa-test-db.env + key: PIKAOA_TEST_DB_PASSWORD + login: true + attributes: + createdb: false + createrole: false + superuser: false databases: - name: sub2api owner: sub2api @@ -606,6 +640,11 @@ objects: encoding: UTF8 locale: C.UTF-8 extensions: [] + - name: pikaoa_test + owner: pikaoa_test + encoding: UTF8 + locale: C.UTF-8 + extensions: [] exports: connectionStrings: @@ -764,6 +803,22 @@ exports: - scope: pikaoa secret: pikaoa-runtime key: DATABASE_URL + - name: pikaoa-test-database-url + sourceSecretRef: platform-db/pikaoa-test-db.env + render: + envKey: DATABASE_URL + format: postgresql://$(PIKAOA_TEST_DB_USER):$(PIKAOA_TEST_DB_PASSWORD)@$(PGHOST):$(PGPORT)/$(PIKAOA_TEST_DB_NAME)?sslmode=require + variables: + PGHOST: 82.156.23.220 + PGPORT: "5432" + writeToSecretSource: + sourceRef: platform-infra/pikaoa-test.env + key: DATABASE_URL + mode: update-or-insert + consumers: + - scope: pikaoa-test + secret: pikaoa-test-runtime + key: DATABASE_URL backup: phase: minimum-restoreable @@ -812,6 +867,9 @@ observability: - kind: psql-app-role database: pikaoa user: pikaoa + - kind: psql-app-role + database: pikaoa_test + user: pikaoa_test - kind: disk-free path: /var/lib/postgresql/16/main minFreeGiB: 10 diff --git a/docs/MDTODO/details/pikaoa-enterprise-platform/R1.5.9.4_Task_Report.md b/docs/MDTODO/details/pikaoa-enterprise-platform/R1.5.9.4_Task_Report.md new file mode 100644 index 00000000..725722cf --- /dev/null +++ b/docs/MDTODO/details/pikaoa-enterprise-platform/R1.5.9.4_Task_Report.md @@ -0,0 +1,36 @@ +# R1.5.9.4 任务报告 + +## 任务结果 + +- 在 `config/platform-db/postgres-pk01.yaml` 声明独立 `pikaoa_test` role、database、凭据 `sourceRef`、连接串 export、NC01 来源 HBA 和有界状态检查。 +- 测试凭据来源为 `platform-db/pikaoa-test-db.env`,连接串写入 `platform-infra/pikaoa-test.env`,consumer 为 `pikaoa-test-runtime/DATABASE_URL`。 +- 保持既有生产 `pikaoa` role、database、Secret export 和 consumer 声明不变。 +- 收紧 `platform-db postgres plan` 的 role、database 和 Secret 默认摘要,确保新增对象后仍保持有界可见。 + +## 交付证据 + +- 执行记录:[pikasTech/unidesk#2078](https://github.com/pikasTech/unidesk/issues/2078)。 +- 提交:[d281b560](https://github.com/pikasTech/unidesk/commit/d281b560746b0cd61b018a5d628490685b62d210)。 +- PR:[pikasTech/unidesk#2083](https://github.com/pikasTech/unidesk/pull/2083)。 + +## 验证摘要 + +- `bun --check scripts/src/platform-db.ts`:通过。 +- `git diff --check`:通过。 +- `bun scripts/cli.ts platform-db postgres plan --config config/platform-db/postgres-pk01.yaml`:显示 `pikaoa_test` role、database、Secret sourceRef 和连接串 export;输出包含 `mutation=false`、`valuesPrinted=false`。 +- `bun scripts/cli.ts platform-db postgres status --config config/platform-db/postgres-pk01.yaml`:对尚未落地的 `pikaoa_test` role、database 和 export 返回有界 actionable 摘要;未执行 mutation。 +- `bun scripts/cli.ts platform-db postgres export-secrets --config config/platform-db/postgres-pk01.yaml --dry-run`:显示独立测试凭据与连接串 export 的 create 计划;输出包含 `mutation=false`、`valuesPrinted=false`。 +- PR preflight:`MERGEABLE/CLEAN`,无 pending 或失败检查。 + +## 执行边界 + +- 未执行 live `platform-db postgres apply`。 +- 未写入任何 Secret source 文件。 +- 未触碰 NC01 k3s 运行对象。 +- 未扩展 PikaOA 产品源码或其他配置范围。 + +## 已知风险 + +- 当前 PK01 状态同时显示既有生产 `pikaoa` role、database 和 export 尚未落地。 +- owning YAML 的 live `apply` 是 shared apply;主代理后续执行时,production `pikaoa` 与新增 `pikaoa_test` 将被同批收敛。 +- 该 shared apply 风险不由本任务提前消除或绕过;执行 live apply 前必须由主代理明确确认影响范围,并继续保持 Secret 脱敏和非阻塞漂移 warning 边界。 diff --git a/docs/MDTODO/pikaoa-enterprise-platform.md b/docs/MDTODO/pikaoa-enterprise-platform.md index 71698319..7c670710 100644 --- a/docs/MDTODO/pikaoa-enterprise-platform.md +++ b/docs/MDTODO/pikaoa-enterprise-platform.md @@ -102,7 +102,7 @@ ##### R1.5.9.3 [completed] 按用户确认方案将测试架构定锚为现有 NC01 k3s 的 pikaoa-test namespace、PK01 host PostgreSQL 独立测试库与角色、YAML hostIP 端口,并更新 SPEC 与 [pikasTech/unidesk#2058](https://github.com/pikasTech/unidesk/issues/2058),完成任务后将详细报告写入[任务报告](./details/pikaoa-enterprise-platform/R1.5.9.3_Task_Report.md)。 -##### R1.5.9.4 [in_progress] +##### R1.5.9.4 [completed] 在 PK01 host PostgreSQL 声明独立 pikaoa_test database/role、Secret export 与 NC01 HBA,执行记录见 [pikasTech/unidesk#2078](https://github.com/pikasTech/unidesk/issues/2078),完成任务后将详细报告写入[任务报告](./details/pikaoa-enterprise-platform/R1.5.9.4_Task_Report.md)。 ##### R1.5.9.5 [in_progress] diff --git a/scripts/src/platform-db.ts b/scripts/src/platform-db.ts index c5da285a..377618f7 100644 --- a/scripts/src/platform-db.ts +++ b/scripts/src/platform-db.ts @@ -1113,27 +1113,28 @@ function compactPlan( transport: pg.postgres.network.transport, sslmode: pg.postgres.network.sslmode, }, - roles: pg.objects.roles.map((role) => ({ + roles: compactActionableSummary(pg.objects.roles.map((role) => ({ name: role.name, exists: observedRoles.find((item) => item.name === role.name)?.exists ?? null, action: observedRoles.some((item) => item.name === role.name && item.exists) ? "none" : "create-or-update", - })), - databases: pg.objects.databases.map((database) => ({ + })), { + passed: (item) => item.action === "none", + missing: (item) => item.exists !== true, + actionable: (item) => item.action !== "none", + project: (item) => item, + }), + databases: compactActionableSummary(pg.objects.databases.map((database) => ({ name: database.name, owner: database.owner, exists: observedDatabases.find((item) => item.name === database.name)?.exists ?? null, action: observedDatabases.some((item) => item.name === database.name && item.exists) ? "none" : "create", - })), - secrets: { - ok: secrets.ok, - root: secrets.root, - entries: secrets.entries.map((entry) => ({ - sourceRef: entry.sourceRef, - missingKeys: entry.missingKeys, - action: entry.action, - })), - valuesPrinted: false, - }, + })), { + passed: (item) => item.action === "none", + missing: (item) => item.exists !== true, + actionable: (item) => item.action !== "none", + project: (item) => item, + }), + secrets: compactSecretInspection(secrets), exports: pg.exports.connectionStrings.map((item) => ({ name: item.name, sourceRef: item.sourceSecretRef,