From 55869acfd5d464b12991d11b46bd4924ee76b90d Mon Sep 17 00:00:00 2001 From: panxiao81 Date: Mon, 14 Sep 2026 14:18:00 +0000 Subject: [PATCH] docs: base extension support on instance capabilities --- docs/api-reference.md | 10 +++++----- docs/architecture.md | 4 ++-- docs/deployment.md | 2 +- docs/domain-instance.md | 24 ++++++++++++++++++++---- docs/domain-model.md | 4 ++-- docs/migration.md | 4 ++-- docs/specification.md | 15 +++++++++++---- 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index 2eb6ae4..7803b61 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -40,15 +40,16 @@ cluster-scoped,short name 为 `pginstance`。 | `spec.adminCredentialRef.name` | string | 必填 | controller namespace 内的管理 Secret 名称 | | `spec.adminCredentialRef.usernameKey` | string | `username` | Secret data 中的键名 | | `spec.adminCredentialRef.passwordKey` | string | `password` | Secret data 中的键名 | -| `spec.allowedExtensions` | set[string] | 空集合 | 合法 extension 名称的 allowlist | `adminCredentialRef` 不接受 namespace 或 Bao path。管理 Secret 固定在 controller namespace,名称须合法,两个字段须存在且非空。管理员维护 ExternalSecret,由 ESO 同步;controller 只读管理 Secret,不创建或修改它。此为 2026-09-13 批准的修订, 现有 API types、生成 CRD 和 samples 尚未更新。 -Instance endpoint、管理凭据引用和 allowlist 可以修改。修改后 controller 重新验证; -删除 allowlist 项目不会自动从已有 Tenant database 删除 extension。 +Instance endpoint、管理凭据引用可以修改。修改后 controller 重新验证。 +2026-09-14 修订:v1alpha1 不实现 allowedExtensions;现有 API types、生成 CRD 和 +samples 中的字段待后续移除,不作为一个可配置但被忽略的策略保留。 +扩展请求按目标 PostgreSQL 实际可安装列表判断,可用列表由应用层查询。 endpoint 由管理员负责,不校验变更前后是否同一物理服务器/registry,只重验新配置 的连接与管理能力。新 UID 按新 Instance 处理,不授权接管旧 UID 的 Tenant 资源。 @@ -81,7 +82,7 @@ namespaced,short name 为 `pgtenant`。 | `spec.instanceRef` | string | 必填 | cluster-scoped Instance 名称 | | `spec.database` | string | `metadata.name` | 合法 PostgreSQL identifier | | `spec.loginRole` | string | `metadata.name` | database owner 兼应用 login | -| `spec.extensions` | set[string] | 空集合 | 必须属于 Instance allowlist;成功创建后只允许追加 | +| `spec.extensions` | set[string] | 空集合 | 必须属于目标实例实际可安装的扩展列表;成功创建后只允许追加 | | `spec.credential.secretName` | string | `--postgresql` | 合法的同 namespace ESO target Secret 名称 | | `spec.deletionPolicy` | enum | `Retain` | `Retain` 或 `Delete` | @@ -172,7 +173,6 @@ spec: sslMode: verify-full adminCredentialRef: name: shared-postgresql-admin - allowedExtensions: [pg_trgm] --- apiVersion: database.ddupan.top/v1alpha1 kind: PostgreSQLTenant diff --git a/docs/architecture.md b/docs/architecture.md index c6b816b..19b9844 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -35,8 +35,8 @@ controller 不运行 PostgreSQL/OpenBao,不管理 VM、存储、备份或 Open ## 资源模型 `PostgreSQLInstance` 是 cluster-scoped,由平台管理员创建,描述外部 PostgreSQL 的 -DNS host、IP host address、端口、管理 database、TLS 模式、管理 Secret 引用和 -extension allowlist。 +DNS host、IP host address、端口、管理 database、TLS 模式和管理 Secret 引用。 +实际可安装扩展由应用层查询后交给领域对象判定,v1alpha1 不实现管理员 allowlist。 管理连接使用管理员维护的 ExternalSecret 经 ESO 同步到 controller namespace 的 Secret;Instance 只选择 Secret 名称与字段,controller 只读,不直接从 Bao 获取 diff --git a/docs/deployment.md b/docs/deployment.md index 4c7605d..90bf3ff 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -69,7 +69,7 @@ base path 必须是合法 mount-relative path,不以 `/` 开头且不包含空 - 创建/修改受管 login role; - 创建 database 并指定 owner; - 撤销 `PUBLIC` CONNECT、授予租户 role CONNECT; -- 连接租户 database 并创建 allowlist extension; +- 连接租户 database 并创建实例实际支持、租户申请的 extension; - 创建和维护 controller 专属 registry schema/table; - `Delete` 时禁止连接、终止目标 database session、删除已验证归属的 database/role。 diff --git a/docs/domain-instance.md b/docs/domain-instance.md index 1824194..6aa0382 100644 --- a/docs/domain-instance.md +++ b/docs/domain-instance.md @@ -34,7 +34,7 @@ registry,不增加安装身份连续性检查;只使旧观察失效,按新 | revision | 正整数,期望配置版本 | metadata.generation | 本轮不可变;不是物理服务器版本 | | definition.endpoint | Endpoint:host、hostaddr、port、managementDatabase、tlsMode | CR spec | 本轮不可变;新配置重验 | | definition.adminCredential | CredentialReference:name、usernameKey、passwordKey | CR spec | 只引用 controller namespace 的管理 Secret,不存明文 | -| definition.allowedExtensions | 去重的 ExtensionName 集合 | CR spec | 本轮不可变;不因 allowlist 缩小卸载扩展 | +| availableExtensions | 可选的实际可安装扩展集合 | 应用层从目标 PostgreSQL 查询;本轮观察,不新增 status 字段 | 未观察与已观察的空集合不同;目标变化后旧结果失效 | | checkpoint | Pending/Validating/InitializingRegistry/Ready/Deleting | CR status.phase | 只能由领域动作变更,应用层负责持久化 | | observedRevision | 最近完成有结论协调的版本 | CR status.observedGeneration | 成功或已知失败时更新,单纯记录意图不更新 | | readiness | Unknown/Ready/NotReady,加安全失败类别和操作说明 | 由 status Ready Condition 重建,结果再映射回 Condition | 方法更新;不是第二套持久化状态 | @@ -58,6 +58,21 @@ SHOW server_version”。具体权限探测矩阵需在 PostgreSQL 适配器规 不属于 Instance 的字段:Tenant 清单、客户端、连接池、token TTL、CA 文件句柄、 Kubernetes resourceVersion。resourceVersion 留在应用层作为乐观并发保存的前提。 +### 扩展支持判定(2026-09-14 已确认方向) + +v1alpha1 按目标 PostgreSQL 实际可安装的扩展列表判断请求,不实现管理员 allowlist。 +allowlist 仅保留为后续可选策略,不接受一个看似生效、实际被忽略的策略字段;现有 +CRD 的 allowedExtensions 应在对应 API 改动中移除,本次只修订文档。 + +应用层查询实际可用扩展并提供与本轮目标绑定的观察;Instance 只做集合判断,不 +访问数据库。不沿用之前提议的字符正则,不自动改大小写或名称;SQL 适配器仍须 +安全引用 identifier。可用列表不是已安装列表,也不保证权限或其他安装前提满足。 + +未观察/查询失败不得当作空集合或不支持;不得用旧目标的列表授权新目标的操作。 +非空请求须属于已观察的可用集合,返回不支持的名称;空请求无需扩展支持判定, +但不绕过 Instance 的其他就绪要求。安装后仍需回读,不能以集合匹配代替安装验证。 +列表变化不触发自动卸载;已有扩展的漂移处理留到 Tenant 用例细化。 + ## 3. 设计签名 ```text @@ -70,7 +85,8 @@ Instance.PlanRegistryPreparation(observation: CapabilityObservation) -> AlreadyUsable | PreparationAllowed | PreparationDenied Instance.AssessRegistryResult(result: RegistryPreparationResult) -> Outcome Instance.AssessReadiness(observation: CapabilityObservation) -> Outcome -Instance.CheckExtensions(requested: ExtensionSet) -> Accepted | ExtensionsDenied +Instance.CheckExtensions(requested: ExtensionSet) + -> Accepted | ExtensionsUnsupported | ExtensionSupportUnobserved Instance.RequireProvisioningReady() -> Accepted | InstanceNotReady Instance.BeginDeletion() -> Outcome Instance.Snapshot() -> InstanceSnapshot @@ -106,7 +122,7 @@ evidence 为空。若 observedRevision 与 revision 不一致,旧 Ready 不得 | PlanRegistryPreparation | 未删除;InitializingRegistry;本轮前置观察 | 根据管理能力及 registry 现状决定无需写入、允许准备或禁止准备;返回决策,不执行迁移、不标 Ready | 访问失败、不兼容或证据不足时禁止写入,NotReady;保持阶段,更新 observedRevision | | AssessRegistryResult | 未删除;InitializingRegistry;准备结果或无需写入时的完整回读 | 按全部就绪条件判断回读结果;全满足才 Ready,并更新 observedRevision/version/evidence | 操作失败或回读不满足时保持 InitializingRegistry、NotReady;不得提前 Ready | | AssessReadiness | 未删除;Ready;本轮观察 | 配置版本不一致时仅 BeginValidation;否则根据全部观察判断是否仍满足就绪条件 | 访问失败转 Validating/NotReady;registry 缺失或需迁移时转 InitializingRegistry,保存后下一轮修复 | -| CheckExtensions | 一组规范化 extension 名称 | 检查请求是否为当前 allowlist 子集,返回不允许的名称;无 IO、无状态修改 | ExtensionsDenied;不卸载已存在 extension | +| CheckExtensions | 请求集合;本轮实际可用扩展观察 | 判断请求是否为实际可用集合的子集,返回不支持的名称;无 IO、无状态修改 | ExtensionsUnsupported 或 ExtensionSupportUnobserved;不卸载已存在扩展 | | RequireProvisioningReady | 供 Tenant 用例使用 | 要求未删除、Ready、observedRevision 匹配,并有本次调用链的新鲜完整 evidence | 不满足即 InstanceNotReady;持久化 Ready 本身不构成授权 | | BeginDeletion | deleting=true | 转 Deleting,清除供应能力,Unknown;不执行任何数据库或凭据删除 | 引用检查/finalizer 处理失败不得恢复成可供应 | | Snapshot | 任意合法对象状态 | 返回可安全持久化的结果值 | 不触发 IO,也不改变状态 | @@ -196,7 +212,7 @@ Ready --registry 需修复/保存--> InitializingRegistry - 首版不为 Instance 删除增加跨对象锁或准入控制。并发创建的 Tenant CR 不被 finalizer 拦截,但遇到删除中/不存在的 Instance 不得开始供应;不承诺取消 已在途的外部操作,也不声称引用查询与移除 finalizer 是跨对象原子事务。 -- CheckExtensions 失败不能产生任何外部写入;修改 allowlist 不会自行卸载扩展。 +- CheckExtensions 失败不能授权扩展安装;可用列表变化不会自行卸载已有扩展。 - Snapshot、错误、日志和领域对象格式化不输出明文凭据或 token。 - 领域测试只提供观察值,无需数据库、网络、context 或 IO mock;相同状态和输入 得到相同决策。缺少检查项、目标不匹配和旧配置结果不得产生 Ready。 diff --git a/docs/domain-model.md b/docs/domain-model.md index 81cd951..606864d 100644 --- a/docs/domain-model.md +++ b/docs/domain-model.md @@ -29,12 +29,12 @@ database OID 是诊断观察值,不充当本系统的租户身份。 ### Instance:实例能力与供应策略 -Instance 是候选聚合根,持有自身身份、endpoint、管理凭据引用、extension allowlist, +Instance 是候选聚合根,持有自身身份、endpoint、管理凭据引用、实际可用扩展观察, 以及用于判断当前能力的观察结果。它不持有所有 Tenant 对象的集合。 其行为包括: -- 判断租户申请是否符合本实例的 extension 策略。 +- 判断租户申请的 extension 是否在本实例实际可安装列表中;v1alpha1 暂不实现 allowlist。 - 根据管理连接、服务器信息、registry 和权限检查结果判断是否具备供应能力。 - 判断配置变化使哪些能力观察过期,禁止以旧 generation 的 Ready 证明新配置可用。 - 在 registry 初始化完成并回读验证后,接受新的就绪结果。 diff --git a/docs/migration.md b/docs/migration.md index cb4d573..a766895 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -33,7 +33,7 @@ pg_dump --schema-only --no-owner --no-privileges \ ``` 检查不受 v1alpha1 管理的对象:额外 roles、跨库依赖、FDW、large objects、订阅、显式 -tablespace、owner/grant 和不在 allowlist 的 extension。无法映射为单 database + 单 login +tablespace、owner/grant 和目标实例不支持的 extension。无法映射为单 database + 单 login owner 的环境必须先人工简化,不能让 controller 猜测。 ### 2. 创建一致性 dump @@ -84,7 +84,7 @@ pg_restore --exit-on-error --no-owner --no-privileges \ ``` extension 应由 Tenant spec 创建。若 dump 仍包含 extension 定义,预演必须确认 restore -行为幂等;不在 allowlist 的 extension 必须在迁移前解决。 +行为幂等;目标实例不支持的 extension 必须在迁移前解决。 ### 6. 验证并切换 diff --git a/docs/specification.md b/docs/specification.md index bd8580c..7ffd04a 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -38,7 +38,7 @@ v1alpha1 必须实现以下目标: 1. 注册一个已经存在的外部 PostgreSQL 实例并报告连接状态。 2. 为一个应用租户创建独立 database 和一个同时作为 database owner 的 login role。 -3. 根据实例 allowlist 安装租户申请的 PostgreSQL extension。 +3. 根据实例实际可安装扩展列表检查并安装租户申请的 PostgreSQL extension。 4. 首次生成高强度长期密码,并只把凭据明文写入 OpenBao KV v2。 5. 为 Kubernetes 应用创建 ExternalSecret,由 ESO 将凭据投射到同 namespace Secret。 6. 同时输出 OpenBao API URL,使 Kubernetes 外的应用可以直接读取凭据。 @@ -93,8 +93,11 @@ PostgreSQL 管理 role。应用或 GitOps 流程在获得 namespace RBAC 后管 - PostgreSQL host、port 和管理连接使用的 database; - PostgreSQL host address,供无法解析 DNS 的消费者使用; - TLS mode; -- controller namespace 中 PostgreSQL 管理 Secret 的名称和字段名; -- 租户允许申请的 extension 集合。 +- controller namespace 中 PostgreSQL 管理 Secret 的名称和字段名。 + +可安装的 extension 集合由应用层从目标 PostgreSQL 查询,不由管理员在 Instance +中声明。v1alpha1 不实现 allowlist;该概念保留为后续可选策略。实际可用不代表安装 +权限及前置条件已满足,安装仍需执行并回读;查询失败不得被解释为扩展不支持。 实例 Ready 不代表 PostgreSQL 数据有备份或高可用,只表示 controller 当前可以安全 建立管理连接、读取 server metadata、访问 controller registry 并使用所需管理能力。 @@ -470,7 +473,8 @@ v1alpha1 至少必须提供: 6. controller 在每个外部写入步骤后中断,重启后都能继续并得到相同最终状态。 7. 预先存在且不属于当前 Tenant UID 的 database、role 或 OpenBao path 导致 Conflict,且不修改已有资源。 -8. 未在 allowlist 的 extension 在任何外部写入前被拒绝。 +8. 目标实例实际不支持的 extension 在供应外部写入前被拒绝;扩展列表查询失败时 + 按依赖故障处理,不报告为不支持。安装结果仍须回读验证。 9. status 被清空后可以从两个外部事实来源重建。 10. 删除 Retain Tenant 后外部资源仍存在且不再受管;重新创建同名 Tenant 报告 Conflict。 @@ -523,6 +527,9 @@ v1alpha1 至少必须提供: ## 17. 批准状态 +2026-09-14 确认 extension 判定修订:v1alpha1 使用实例实际可安装列表,不实现管理员 +allowlist;后续可按需引入策略。现有 allowedExtensions 字段尚待 API 实现移除。 + 2026-09-13 已确认管理连接修订:Instance 引用 controller namespace 内的管理 Secret, 管理员维护 ExternalSecret,由 ESO 同步;controller 不再从 Bao 直接读取管理凭据。 此项是已批准行为,现有 API types 与实现尚待后续修改。