refactor: 集中显式注入并归位凭据领域规则
This commit is contained in:
@@ -51,11 +51,3 @@ func tenantReference(tenant binding.TenantIdentity) *databasev1alpha1.TenantRefe
|
||||
Namespace: tenant.Namespace, Name: databasev1alpha1.ObjectName(tenant.Name), UID: types.UID(tenant.UID),
|
||||
}
|
||||
}
|
||||
|
||||
// BindingTargetName 供 informer 索引使用;不把无效请求丢出事件映射。
|
||||
func BindingTargetName(tenant *databasev1alpha1.PostgreSQLTenant) string {
|
||||
if tenant.Spec.DatabaseRef != nil {
|
||||
return string(tenant.Spec.DatabaseRef.Name)
|
||||
}
|
||||
return binding.DynamicDatabaseName(string(tenant.UID))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package kubernetes
|
||||
|
||||
import credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
const credentialsReadyCondition = "CredentialsReady"
|
||||
|
||||
// 持久化 API 的 Reason 保持兼容,领域内部只使用准备阶段。
|
||||
var credentialReasons = map[credentialdomain.Phase]string{
|
||||
credentialdomain.Pending: "PreparationPending",
|
||||
credentialdomain.Pinned: "LocationPinned",
|
||||
credentialdomain.Creating: "CreationStarted",
|
||||
credentialdomain.Prepared: "CredentialPrepared",
|
||||
credentialdomain.Conflict: "Conflict",
|
||||
credentialdomain.Unavailable: "DependencyUnavailable",
|
||||
credentialdomain.Stopped: "PreparationStopped",
|
||||
credentialdomain.InvalidTarget: "InvalidTarget",
|
||||
}
|
||||
|
||||
func credentialReason(phase credentialdomain.Phase) string { return credentialReasons[phase] }
|
||||
|
||||
func credentialPhase(reason string) credentialdomain.Phase {
|
||||
for phase, value := range credentialReasons {
|
||||
if value == reason {
|
||||
return phase
|
||||
}
|
||||
}
|
||||
return credentialdomain.Pending
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
databasev1alpha1 "git.ddupan.top/panxiao81/ayatori/api/database/v1alpha1"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/domain/binding"
|
||||
@@ -30,8 +32,9 @@ func (r *CredentialResources) Load(ctx context.Context, name string) (*applicati
|
||||
return nil, client.IgnoreNotFound(err)
|
||||
}
|
||||
record := &application.CredentialRecord{
|
||||
Database: *bindingDatabase(database), DatabaseProtected: controllerutil.ContainsFinalizer(database, DatabaseFinalizer),
|
||||
Status: credentialStatus(database),
|
||||
Database: bindingDatabase(database).Database, Revision: database.ResourceVersion,
|
||||
DatabaseProtected: controllerutil.ContainsFinalizer(database, DatabaseFinalizer),
|
||||
Status: credentialStatus(database),
|
||||
}
|
||||
if database.Spec.Source != "Provision" {
|
||||
return record, nil
|
||||
@@ -43,7 +46,8 @@ func (r *CredentialResources) Load(ctx context.Context, name string) (*applicati
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
record.Tenant = bindingTenant(tenant)
|
||||
record.Tenant = &bindingTenant(tenant).Tenant
|
||||
record.TenantGeneration = tenant.Generation
|
||||
record.TenantProtected = controllerutil.ContainsFinalizer(tenant, TenantFinalizer)
|
||||
}
|
||||
}
|
||||
@@ -56,29 +60,29 @@ func (r *CredentialResources) Load(ctx context.Context, name string) (*applicati
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
record.Instance = &application.CredentialInstance{
|
||||
record.Instance = &credentialdomain.Instance{
|
||||
Identity: binding.Identity{Name: instance.Name, UID: string(instance.UID)},
|
||||
Deleting: !instance.DeletionTimestamp.IsZero(), Ready: currentReady(instance.Generation, instance.Status.Conditions),
|
||||
Generation: instance.Generation, Endpoint: observed.Target.Definition().Endpoint(),
|
||||
Endpoint: observed.Target.Definition().Endpoint(),
|
||||
}
|
||||
record.InstanceGeneration = instance.Generation
|
||||
return record, nil
|
||||
}
|
||||
|
||||
func credentialStatus(database *databasev1alpha1.PostgreSQLDatabase) application.CredentialStatus {
|
||||
status := application.CredentialStatus{Version: database.Status.CredentialVersion}
|
||||
func credentialStatus(database *databasev1alpha1.PostgreSQLDatabase) credentialdomain.State {
|
||||
status := credentialdomain.State{Version: database.Status.CredentialVersion}
|
||||
if ref := database.Status.CredentialRef; ref != nil {
|
||||
status.Location = &application.CredentialLocation{Mount: ref.Mount, Path: ref.Path}
|
||||
status.Location = &credentialdomain.Location{Mount: ref.Mount, Path: ref.Path}
|
||||
}
|
||||
if condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady); condition != nil {
|
||||
status.Ready = condition.Status == metav1.ConditionTrue && condition.ObservedGeneration == database.Generation
|
||||
status.Reason, status.Message = condition.Reason, condition.Message
|
||||
if condition := meta.FindStatusCondition(database.Status.Conditions, credentialsReadyCondition); condition != nil {
|
||||
status.Phase, status.Message = credentialPhase(condition.Reason), condition.Message
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
func (r *CredentialResources) Save(ctx context.Context, record *application.CredentialRecord, status application.CredentialStatus) (*application.CredentialRecord, error) {
|
||||
func (r *CredentialResources) Save(ctx context.Context, record *application.CredentialRecord, status credentialdomain.State) (*application.CredentialRecord, error) {
|
||||
bindingResources := &BindingResources{Client: r.Client, Reader: r.Reader}
|
||||
database, err := bindingResources.databaseAtVersion(ctx, &record.Database)
|
||||
database, err := bindingResources.databaseAtVersion(ctx, &application.BindingDatabase{Database: record.Database, Revision: record.Revision})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -88,11 +92,11 @@ func (r *CredentialResources) Save(ctx context.Context, record *application.Cred
|
||||
}
|
||||
database.Status.CredentialVersion = status.Version
|
||||
conditionStatus := metav1.ConditionFalse
|
||||
if status.Ready {
|
||||
if status.Phase == credentialdomain.Prepared {
|
||||
conditionStatus = metav1.ConditionTrue
|
||||
}
|
||||
meta.SetStatusCondition(&database.Status.Conditions, metav1.Condition{
|
||||
Type: application.CredentialsReady, Status: conditionStatus, Reason: status.Reason, Message: status.Message,
|
||||
Type: credentialsReadyCondition, Status: conditionStatus, Reason: credentialReason(status.Phase), Message: status.Message,
|
||||
ObservedGeneration: database.Generation,
|
||||
})
|
||||
meta.SetStatusCondition(&database.Status.Conditions, metav1.Condition{
|
||||
@@ -106,7 +110,8 @@ func (r *CredentialResources) Save(ctx context.Context, record *application.Cred
|
||||
}
|
||||
}
|
||||
updated := *record
|
||||
updated.Database = *bindingDatabase(database)
|
||||
updated.Database = bindingDatabase(database).Database
|
||||
updated.Revision = database.ResourceVersion
|
||||
updated.Status = credentialStatus(database)
|
||||
// 旧 CRD 会裁剪未知 status 字段。不能把 HTTP 成功当作位置/版本已保存后继续写后端。
|
||||
if !equality.Semantic.DeepEqual(updated.Status.Location, status.Location) || updated.Status.Version != status.Version {
|
||||
@@ -120,7 +125,7 @@ func (r *CredentialResources) CheckCurrent(ctx context.Context, record *applicat
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if current == nil || current.Database.Identity != record.Database.Identity || current.Database.Revision != record.Database.Revision ||
|
||||
if current == nil || current.Database.Identity != record.Database.Identity || current.Revision != record.Revision ||
|
||||
!sameCredentialDependencies(current, record) {
|
||||
return apierrors.NewConflict(databasev1alpha1.GroupVersion.WithResource("postgresqldatabases").GroupResource(), record.Database.Identity.Name,
|
||||
fmt.Errorf("凭据准备的资源快照已变化;停止本轮操作并重新观察"))
|
||||
@@ -134,9 +139,9 @@ func sameCredentialDependencies(current, previous *application.CredentialRecord)
|
||||
}
|
||||
// Tenant Ready 的诊断变化、Instance 对同一 generation 的观测刷新不改变写入目标。
|
||||
// 仍检查申请 spec generation、完整绑定身份、删除状态、保护和当前 Instance Ready。
|
||||
return current.Tenant.Generation == previous.Tenant.Generation &&
|
||||
equality.Semantic.DeepEqual(current.Tenant.Tenant, previous.Tenant.Tenant) &&
|
||||
return current.TenantGeneration == previous.TenantGeneration &&
|
||||
equality.Semantic.DeepEqual(current.Tenant, previous.Tenant) &&
|
||||
current.TenantProtected == previous.TenantProtected && current.DatabaseProtected == previous.DatabaseProtected &&
|
||||
current.Instance.Instance == previous.Instance.Instance && current.Instance.Generation == previous.Instance.Generation &&
|
||||
current.Instance.Instance == previous.Instance.Instance && current.InstanceGeneration == previous.InstanceGeneration &&
|
||||
current.Instance.Endpoint == previous.Instance.Endpoint
|
||||
}
|
||||
|
||||
@@ -3,22 +3,24 @@ package openbao
|
||||
import (
|
||||
"context"
|
||||
|
||||
credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
)
|
||||
|
||||
var _ application.CredentialStore = (*Credentials)(nil)
|
||||
|
||||
func (c *Credentials) ProvisionLocation(uid string) (application.CredentialLocation, error) {
|
||||
func (c *Credentials) ProvisionLocation(uid string) (credentialdomain.Location, error) {
|
||||
path, err := c.ProvisionPath(uid)
|
||||
if err != nil {
|
||||
return application.CredentialLocation{}, err
|
||||
return credentialdomain.Location{}, err
|
||||
}
|
||||
return application.CredentialLocation{Mount: c.mount, Path: path}, nil
|
||||
return credentialdomain.Location{Mount: c.mount, Path: path}, nil
|
||||
}
|
||||
|
||||
func (c *Credentials) ReadCredential(ctx context.Context, location application.CredentialLocation, version int64) (application.ApplicationCredential, error) {
|
||||
func (c *Credentials) ReadCredential(ctx context.Context, location credentialdomain.Location, version int64) (credentialdomain.ApplicationCredential, error) {
|
||||
if location.Mount != c.mount {
|
||||
return application.ApplicationCredential{}, ErrInvalidLocation
|
||||
return credentialdomain.ApplicationCredential{}, ErrInvalidLocation
|
||||
}
|
||||
if version == 0 {
|
||||
return c.Read(ctx, location.Path)
|
||||
@@ -26,7 +28,7 @@ func (c *Credentials) ReadCredential(ctx context.Context, location application.C
|
||||
return c.ReadConfirmed(ctx, location.Path, version)
|
||||
}
|
||||
|
||||
func (c *Credentials) CreateCredential(ctx context.Context, location application.CredentialLocation, credential application.ApplicationCredential) (int64, error) {
|
||||
func (c *Credentials) CreateCredential(ctx context.Context, location credentialdomain.Location, credential credentialdomain.ApplicationCredential) (int64, error) {
|
||||
if location.Mount != c.mount {
|
||||
return 0, ErrInvalidLocation
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
bao "github.com/openbao/openbao/api/v2"
|
||||
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
@@ -80,33 +82,33 @@ func (c *Credentials) accepts(path string) bool {
|
||||
}
|
||||
|
||||
// Read 只读取调用方已确认关联的路径;成功读取不构成对既有凭据的自动认领。
|
||||
func (c *Credentials) Read(ctx context.Context, path string) (application.ApplicationCredential, error) {
|
||||
func (c *Credentials) Read(ctx context.Context, path string) (credentialdomain.ApplicationCredential, error) {
|
||||
secret, err := c.read(ctx, path)
|
||||
if err != nil {
|
||||
return application.ApplicationCredential{}, err
|
||||
return credentialdomain.ApplicationCredential{}, err
|
||||
}
|
||||
return application.ParseApplicationCredential(secret.Data)
|
||||
return credentialdomain.ParseApplicationCredential(secret.Data)
|
||||
}
|
||||
|
||||
// ReadConfirmed 读取最新值并核对已持久化的确认版本,不回退读取历史版本。
|
||||
// 确认后的删除或改写需要人工处理,不能因此重新生成密码。
|
||||
func (c *Credentials) ReadConfirmed(ctx context.Context, path string, version int64) (application.ApplicationCredential, error) {
|
||||
func (c *Credentials) ReadConfirmed(ctx context.Context, path string, version int64) (credentialdomain.ApplicationCredential, error) {
|
||||
if version < 1 {
|
||||
return application.ApplicationCredential{}, ErrConflict
|
||||
return credentialdomain.ApplicationCredential{}, ErrConflict
|
||||
}
|
||||
secret, err := c.read(ctx, path)
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
return application.ApplicationCredential{}, ErrConflict
|
||||
return credentialdomain.ApplicationCredential{}, ErrConflict
|
||||
}
|
||||
if err != nil {
|
||||
return application.ApplicationCredential{}, err
|
||||
return credentialdomain.ApplicationCredential{}, err
|
||||
}
|
||||
if secret.VersionMetadata == nil || int64(secret.VersionMetadata.Version) != version {
|
||||
return application.ApplicationCredential{}, ErrConflict
|
||||
return credentialdomain.ApplicationCredential{}, ErrConflict
|
||||
}
|
||||
credential, err := application.ParseApplicationCredential(secret.Data)
|
||||
credential, err := credentialdomain.ParseApplicationCredential(secret.Data)
|
||||
if err != nil {
|
||||
return application.ApplicationCredential{}, ErrConflict
|
||||
return credentialdomain.ApplicationCredential{}, ErrConflict
|
||||
}
|
||||
return credential, nil
|
||||
}
|
||||
@@ -130,7 +132,7 @@ func (c *Credentials) read(ctx context.Context, path string) (*bao.KVSecret, err
|
||||
|
||||
// Create 只创建从未存在过的路径,并验证回读七键与提交值完全一致。
|
||||
// 任何不确定写入都不返回凭据;上层必须停止供应并持久化冲突,不能重新生成密码。
|
||||
func (c *Credentials) Create(ctx context.Context, path string, credential application.ApplicationCredential) error {
|
||||
func (c *Credentials) Create(ctx context.Context, path string, credential credentialdomain.ApplicationCredential) error {
|
||||
if !c.accepts(path) {
|
||||
return ErrInvalidLocation
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@ import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
bao "github.com/openbao/openbao/api/v2"
|
||||
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/adapter/openbao"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,9 +40,9 @@ const (
|
||||
kvVersionKey = "version"
|
||||
)
|
||||
|
||||
func fixtureCredential(t *testing.T) application.ApplicationCredential {
|
||||
func fixtureCredential(t *testing.T) credentialdomain.ApplicationCredential {
|
||||
t.Helper()
|
||||
credential, err := application.ParseApplicationCredential(map[string]any{
|
||||
credential, err := credentialdomain.ParseApplicationCredential(map[string]any{
|
||||
"username": "app_owner", "password": fixturePassword, "database": "app",
|
||||
"host": "postgres.example", "hostaddr": "192.0.2.1", "port": "5432", "sslmode": "verify-full",
|
||||
})
|
||||
|
||||
@@ -54,7 +54,7 @@ func testPreparationConcurrency(t *testing.T, f *preparationFixture) {
|
||||
if succeeded != 1 || conflicted != 1 {
|
||||
t.Fatal("同一快照只能有一个用例成功固定位置并继续创建")
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
stored, err := f.bao.KVv2("secret").Get(t.Context(), database.Status.CredentialRef.Path)
|
||||
if err != nil || stored.VersionMetadata.Version != 1 {
|
||||
t.Fatal("并发准备用例只能产生一个凭据版本")
|
||||
|
||||
@@ -80,7 +80,8 @@ func (f *preparationFixture) bound(t *testing.T, name string) (*databasev1alpha1
|
||||
if err := f.api.Create(t.Context(), tenant); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
binder := &databasecontroller.BindingReconciler{Client: f.api, Reader: f.api}
|
||||
resources := &kubernetes.BindingResources{Client: f.api, Reader: f.api}
|
||||
binder := databasecontroller.NewBindingReconciler(f.api, &application.BindingService{Resources: resources}, resources)
|
||||
if _, err := binder.Reconcile(t.Context(), ctrl.Request{NamespacedName: client.ObjectKeyFromObject(tenant)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -106,7 +107,7 @@ func (f *preparationFixture) status(t *testing.T, database *databasev1alpha1.Pos
|
||||
if err := f.api.Get(t.Context(), client.ObjectKeyFromObject(database), database); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady)
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, "CredentialsReady")
|
||||
if database.Status.CredentialVersion != version || condition == nil || condition.Reason != reason {
|
||||
t.Fatalf("凭据版本或条件不符:version=%d,期望 reason=%s", database.Status.CredentialVersion, reason)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"maps"
|
||||
"testing"
|
||||
|
||||
credentialdomain "git.ddupan.top/panxiao81/ayatori/internal/database/domain/credential"
|
||||
|
||||
bao "github.com/openbao/openbao/api/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
@@ -36,7 +38,7 @@ func testPreparationRestart(t *testing.T, f *preparationFixture) {
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
path := database.Status.CredentialRef.Path
|
||||
before, err := f.bao.KVv2("secret").Get(t.Context(), path)
|
||||
if err != nil {
|
||||
@@ -51,12 +53,12 @@ func testPreparationRestart(t *testing.T, f *preparationFixture) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
revision := database.ResourceVersion
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
if database.ResourceVersion != revision {
|
||||
t.Fatal("幂等重试不应改写 status")
|
||||
}
|
||||
@@ -135,7 +137,7 @@ func testPreparationLostConfirmation(t *testing.T, f *preparationFixture) {
|
||||
if err := service.Reconcile(t.Context(), database.Name); err == nil {
|
||||
t.Fatal("确认写入失败应返回 API 错误")
|
||||
}
|
||||
f.status(t, database, 0, application.CredentialCreationStarted)
|
||||
f.status(t, database, 0, "CreationStarted")
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -151,7 +153,7 @@ type afterCreateStore struct {
|
||||
after func() error
|
||||
}
|
||||
|
||||
func (s afterCreateStore) CreateCredential(ctx context.Context, location application.CredentialLocation, credential application.ApplicationCredential) (int64, error) {
|
||||
func (s afterCreateStore) CreateCredential(ctx context.Context, location credentialdomain.Location, credential credentialdomain.ApplicationCredential) (int64, error) {
|
||||
version, err := s.CredentialStore.CreateCredential(ctx, location, credential)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -185,7 +187,7 @@ func testPreparationChangedBinding(t *testing.T, f *preparationFixture) {
|
||||
if err := service.Reconcile(t.Context(), database.Name); err == nil {
|
||||
t.Fatal("中途删除 Tenant 后不得确认凭据")
|
||||
}
|
||||
f.status(t, database, 0, application.CredentialCreationStarted)
|
||||
f.status(t, database, 0, "CreationStarted")
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -205,7 +207,7 @@ func testPreparationDependencies(t *testing.T, f *preparationFixture) {
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
if err := service.Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -213,7 +215,7 @@ func testPreparationDependencies(t *testing.T, f *preparationFixture) {
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
moved, err := openbao.NewCredentials(f.bao, "other", "elsewhere")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
databasev1alpha1 "git.ddupan.top/panxiao81/ayatori/api/database/v1alpha1"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/adapter/kubernetes"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
)
|
||||
|
||||
// 在 API 边界模拟旧 schema 裁剪位置字段;剩余写入仍由真实 API server 处理。
|
||||
@@ -48,5 +47,5 @@ func testPreparationPruning(t *testing.T, f *preparationFixture) {
|
||||
if err := f.service(t).Reconcile(t.Context(), database.Name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.status(t, database, 1, application.CredentialPrepared)
|
||||
f.status(t, database, 1, "CredentialPrepared")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/adapter/kubernetes"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
@@ -15,7 +18,6 @@ import (
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
|
||||
databasev1alpha1 "git.ddupan.top/panxiao81/ayatori/api/database/v1alpha1"
|
||||
"git.ddupan.top/panxiao81/ayatori/internal/database/application"
|
||||
databasecontroller "git.ddupan.top/panxiao81/ayatori/internal/database/controller"
|
||||
)
|
||||
|
||||
@@ -26,7 +28,7 @@ func testPreparationWatch(t *testing.T, f *preparationFixture) {
|
||||
return
|
||||
}
|
||||
if err := f.api.Get(context.Background(), client.ObjectKeyFromObject(database), database); err == nil {
|
||||
if condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady); condition != nil {
|
||||
if condition := meta.FindStatusCondition(database.Status.Conditions, "CredentialsReady"); condition != nil {
|
||||
t.Logf("失败时凭据条件: %s: %s", condition.Reason, condition.Message)
|
||||
}
|
||||
}
|
||||
@@ -50,7 +52,7 @@ func testPreparationWatch(t *testing.T, f *preparationFixture) {
|
||||
if err := f.api.Get(t.Context(), client.ObjectKeyFromObject(database), database); err != nil {
|
||||
return false
|
||||
}
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady)
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, "CredentialsReady")
|
||||
return condition != nil && condition.Reason == "DependencyUnavailable"
|
||||
})
|
||||
if database.Status.CredentialRef != nil {
|
||||
@@ -69,7 +71,7 @@ func testPreparationWatch(t *testing.T, f *preparationFixture) {
|
||||
if err := f.api.Get(t.Context(), client.ObjectKeyFromObject(database), database); err != nil {
|
||||
return false
|
||||
}
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady)
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, "CredentialsReady")
|
||||
return condition != nil && condition.Status == metav1.ConditionFalse && condition.Reason == "DependencyUnavailable"
|
||||
})
|
||||
setReady(metav1.ConditionTrue)
|
||||
@@ -77,7 +79,7 @@ func testPreparationWatch(t *testing.T, f *preparationFixture) {
|
||||
if err := f.api.Get(t.Context(), client.ObjectKeyFromObject(database), database); err != nil {
|
||||
return false
|
||||
}
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, application.CredentialsReady)
|
||||
condition := meta.FindStatusCondition(database.Status.Conditions, "CredentialsReady")
|
||||
return condition != nil && condition.Status == metav1.ConditionTrue && database.Status.CredentialVersion == 1
|
||||
})
|
||||
stored, err := f.bao.KVv2("secret").Get(t.Context(), database.Status.CredentialRef.Path)
|
||||
@@ -96,10 +98,14 @@ func startPreparationManager(t *testing.T, f *preparationFixture) func() {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := (&databasecontroller.BindingReconciler{}).SetupWithManager(t.Context(), manager); err != nil {
|
||||
bindingResources := &kubernetes.BindingResources{Client: manager.GetClient(), Reader: manager.GetAPIReader()}
|
||||
binder := databasecontroller.NewBindingReconciler(manager.GetClient(), &application.BindingService{Resources: bindingResources}, bindingResources)
|
||||
if err := binder.SetupWithManager(t.Context(), manager); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := (&databasecontroller.CredentialReconciler{Store: fixtureStore(t, f.bao)}).SetupWithManager(manager); err != nil {
|
||||
credentialResources := &kubernetes.CredentialResources{Client: manager.GetClient(), Reader: manager.GetAPIReader()}
|
||||
preparation := &application.CredentialPreparation{Resources: credentialResources, Store: fixtureStore(t, f.bao)}
|
||||
if err := databasecontroller.NewCredentialReconciler(manager.GetClient(), preparation).SetupWithManager(manager); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
|
||||
@@ -68,7 +68,9 @@ func TestInstanceControllerWithRealPostgreSQL(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
reconciler := &databasecontroller.InstanceReconciler{Observer: service, SecretNamespace: controllerNamespace}
|
||||
resources := &secretadapter.InstanceResources{Client: manager.GetClient(), Reader: manager.GetAPIReader()}
|
||||
usecase := &application.InstanceReconciliation{Resources: resources, Observer: service}
|
||||
reconciler := databasecontroller.NewInstanceReconciler(manager.GetClient(), usecase, resources, controllerNamespace)
|
||||
if err := reconciler.SetupWithManager(manager); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user