test: verify Instance readiness end to end
E2E Tests / Run on Ubuntu (pull_request) Failing after 1m6s
Tests / Run on Ubuntu (pull_request) Successful in 3m55s
Lint / Run on Ubuntu (pull_request) Successful in 4m19s

This commit is contained in:
2026-09-10 18:15:50 +00:00
parent 97f66669a6
commit 212ca4be99
3 changed files with 187 additions and 5 deletions
+4 -3
View File
@@ -171,9 +171,10 @@ E2E fixture 必须把测试 PostgreSQL、OpenBao 和 ESO 部署进 Kind,并等
-> 删除 Kind
```
当前 controller 只实现 PostgreSQL registry adapter,尚未实现完整 PostgreSQL/OpenBao
provisioning;现有 E2E 只能验证 CRD、manager Deployment 和 metrics endpoint。上述真实依赖 fixture 应与第一个完整
reconcile 纵向切片一起实现,不能在文档中声称已经通过。
当前 controller 已实现第一条 Instance Ready 纵向链路:E2E fixture 在 Kind 内启动
PostgreSQL/OpenBao,配置 Kubernetes auth,验证管理凭据读取、PostgreSQL 登录、registry
migration 和 Instance Ready。Tenant provisioning、ESO、TLS DNS/IP SAN 与删除路径仍需
后续纵向切片覆盖,不能从 Instance Ready 推断这些合同已经通过。
## 测试数据与泄漏检查
+85 -2
View File
@@ -36,6 +36,8 @@ import (
// namespace where the project is deployed in
const namespace = "postgresql-tenant-operator-system"
const dependencyNamespace = "postgresql-tenant-operator-e2e"
// serviceAccountName created for the project
const serviceAccountName = "postgresql-tenant-operator-controller-manager"
@@ -52,9 +54,19 @@ var _ = Describe("Manager", Ordered, func() {
// enforce the restricted security policy to the namespace, installing CRDs,
// and deploying the controller.
BeforeAll(func() {
By("creating manager namespace")
cmd := exec.Command("kubectl", "create", "ns", namespace)
By("deploying disposable PostgreSQL and OpenBao dependencies")
cmd := exec.Command("kubectl", "apply", "-f", "test/e2e/fixtures/instance-dependencies.yaml")
_, err := utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to deploy Instance dependencies")
cmd = exec.Command("kubectl", "wait", "deployment/postgres", "deployment/openbao", "--for=condition=Available",
"-n", dependencyNamespace, "--timeout=3m")
_, err = utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Instance dependencies did not become available")
configureOpenBao()
By("creating manager namespace")
cmd = exec.Command("kubectl", "create", "ns", namespace)
_, err = utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to create namespace")
By("labeling the namespace to enforce the restricted security policy")
@@ -72,6 +84,13 @@ var _ = Describe("Manager", Ordered, func() {
cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", managerImage))
_, err = utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to deploy the controller-manager")
By("configuring the controller for disposable dependencies")
argsPatch := `{"spec":{"template":{"spec":{"containers":[{"name":"manager","args":["--leader-elect","--health-probe-bind-address=:8081","--openbao-address=http://openbao.postgresql-tenant-operator-e2e.svc:8200","--openbao-auth-role=postgresql-tenant-operator","--openbao-kv-mount=secret","--external-secret-store-name=openbao"]}]}}}}`
cmd = exec.Command("kubectl", "patch", "deployment", "postgresql-tenant-operator-controller-manager",
"-n", namespace, "--type=strategic", "-p", argsPatch)
_, err = utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to configure controller dependency flags")
})
// After all tests have been executed, clean up by undeploying the controller, uninstalling CRDs,
@@ -92,6 +111,10 @@ var _ = Describe("Manager", Ordered, func() {
By("removing manager namespace")
cmd = exec.Command("kubectl", "delete", "ns", namespace)
_, _ = utils.Run(cmd)
By("removing disposable Instance dependencies")
cmd = exec.Command("kubectl", "delete", "-f", "test/e2e/fixtures/instance-dependencies.yaml", "--ignore-not-found")
_, _ = utils.Run(cmd)
})
// After each test, check for failures and collect logs, events,
@@ -268,6 +291,47 @@ var _ = Describe("Manager", Ordered, func() {
Eventually(verifyMetricsAvailable, 2*time.Minute).Should(Succeed())
})
It("should make an Instance Ready after validating OpenBao and initializing PostgreSQL", func() {
serviceIP, err := utils.Run(exec.Command("kubectl", "get", "service", "postgres", "-n", dependencyNamespace,
"-o", "jsonpath={.spec.clusterIP}"))
Expect(err).NotTo(HaveOccurred())
manifest := fmt.Sprintf(`apiVersion: database.ddupan.top/v1alpha1
kind: PostgreSQLInstance
metadata:
name: e2e
spec:
endpoint:
host: postgres.%s.svc
hostaddr: %s
port: 5432
database: postgres
sslMode: disable
adminCredentialRef:
path: infrastructure/postgresql/admin
`, dependencyNamespace, serviceIP)
manifestPath := filepath.Join(GinkgoT().TempDir(), "instance.yaml")
Expect(os.WriteFile(manifestPath, []byte(manifest), 0o600)).To(Succeed())
_, err = utils.Run(exec.Command("kubectl", "apply", "-f", manifestPath))
Expect(err).NotTo(HaveOccurred())
Eventually(func(g Gomega) {
phase, err := utils.Run(exec.Command("kubectl", "get", "postgresqlinstance", "e2e",
"-o", "jsonpath={.status.phase}"))
g.Expect(err).NotTo(HaveOccurred())
g.Expect(phase).To(Equal("Ready"))
ready, err := utils.Run(exec.Command("kubectl", "get", "postgresqlinstance", "e2e",
"-o", `jsonpath={.status.conditions[?(@.type=="Ready")].status}`))
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ready).To(Equal("True"))
}).Should(Succeed())
output, err := utils.Run(exec.Command("kubectl", "exec", "deployment/postgres", "-n", dependencyNamespace,
"--", "psql", "-U", "postgres", "-d", "postgres", "-Atc",
"SELECT to_regclass('postgresql_tenant_operator.tenant_ownership') IS NOT NULL"))
Expect(err).NotTo(HaveOccurred())
Expect(output).To(Equal("t\n"))
})
// +kubebuilder:scaffold:e2e-webhooks-checks
// TODO: Customize the e2e test suite with scenarios specific to your project.
@@ -282,6 +346,25 @@ var _ = Describe("Manager", Ordered, func() {
})
})
func configureOpenBao() {
By("configuring OpenBao Kubernetes auth and the PostgreSQL administrative credential")
script := `set -eu
bao auth enable kubernetes
bao write auth/kubernetes/config kubernetes_host=https://kubernetes.default.svc \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
printf 'path "secret/data/infrastructure/postgresql/admin" { capabilities = ["read"] }\n' | bao policy write postgresql-tenant-operator -
bao write auth/kubernetes/role/postgresql-tenant-operator \
bound_service_account_names=postgresql-tenant-operator-controller-manager \
bound_service_account_namespaces=postgresql-tenant-operator-system \
policies=postgresql-tenant-operator ttl=5m
bao kv put secret/infrastructure/postgresql/admin username=postgres password=postgres-e2e-only
`
cmd := exec.Command("kubectl", "exec", "deployment/openbao", "-n", dependencyNamespace, "--", "sh", "-ec", script)
_, err := utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to configure OpenBao")
}
// serviceAccountToken returns a token for the specified service account in the given namespace.
// It uses the Kubernetes TokenRequest API to generate a token by directly sending a request
// and parsing the resulting token from the API response.
@@ -0,0 +1,98 @@
apiVersion: v1
kind: Namespace
metadata:
name: postgresql-tenant-operator-e2e
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: openbao
namespace: postgresql-tenant-operator-e2e
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: postgresql-tenant-operator-e2e-openbao-token-reviewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: openbao
namespace: postgresql-tenant-operator-e2e
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: postgresql-tenant-operator-e2e
spec:
replicas: 1
selector:
matchLabels: {app: postgres}
template:
metadata:
labels: {app: postgres}
spec:
containers:
- name: postgres
image: postgres:17-alpine
env:
- {name: POSTGRES_USER, value: postgres}
- {name: POSTGRES_PASSWORD, value: postgres-e2e-only}
ports:
- {name: postgresql, containerPort: 5432}
readinessProbe:
exec: {command: [pg_isready, -U, postgres]}
initialDelaySeconds: 2
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: postgresql-tenant-operator-e2e
spec:
selector: {app: postgres}
ports:
- {name: postgresql, port: 5432, targetPort: postgresql}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: openbao
namespace: postgresql-tenant-operator-e2e
spec:
replicas: 1
selector:
matchLabels: {app: openbao}
template:
metadata:
labels: {app: openbao}
spec:
serviceAccountName: openbao
containers:
- name: openbao
image: openbao/openbao:2.6.1
args: [server, -dev]
env:
- {name: BAO_DEV_LISTEN_ADDRESS, value: "0.0.0.0:8200"}
- {name: BAO_DEV_ROOT_TOKEN_ID, value: dev-only-root-token}
- {name: BAO_ADDR, value: "http://127.0.0.1:8200"}
ports:
- {name: http, containerPort: 8200}
readinessProbe:
exec: {command: [bao, status]}
initialDelaySeconds: 2
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: openbao
namespace: postgresql-tenant-operator-e2e
spec:
selector: {app: openbao}
ports:
- {name: http, port: 8200, targetPort: http}