@using EntKube.Web.Data @using EntKube.Web.Services @inject DatabaseService DatabaseService @inject CnpgService CnpgService @inject MongoService MongoService @inject StorageService StorageService @inject RegisteredPostgresService RegisteredPostgresService @* =========================================================================== Databases Tab — shows CNPG PostgreSQL clusters and MongoDB clusters discovered across the tenant's Kubernetes clusters. Requires the respective operators (cloudnative-pg, mongodb-operator) to be installed on at least one cluster. =========================================================================== *@ @if (loading) {
Discovering database clusters...
@rpi.Notes
} @* ── Pod Health ── *@| Pod | Status | Ready | Node | Age | Restarts |
|---|---|---|---|---|---|
| @pod.Name | @if (pod.Status == "Running") { @pod.Status } else if (pod.Status is "Pending" or "ContainerCreating") { @pod.Status } else { @pod.Status } | @if (pod.Ready) { } else { } | @(pod.Node ?? "—") |
@if (pod.StartTime.HasValue)
{
@((DateTime.UtcNow - pod.StartTime.Value) switch
{
var d when d.TotalDays >= 1 => $"{(int)d.TotalDays}d",
var d when d.TotalHours >= 1 => $"{(int)d.TotalHours}h",
var d => $"{(int)d.TotalMinutes}m"
})
}
else { |
@pod.Restarts |
Pod info unavailable.
}Register an existing database without creating it on the server. Stores the provided credentials in the vault.
No databases managed yet.
} else {| Database | Owner Role | Status | Actions |
|---|---|---|---|
| @db.Name | @db.Owner | @switch (db.Status) { case RegisteredPostgresDatabaseStatus.Ready: Ready break; case RegisteredPostgresDatabaseStatus.Creating: Creating break; case RegisteredPostgresDatabaseStatus.Deleting: Deleting break; default: Failed break; } |
|
|
Remove @db.Name?
|
|||
|
@dumpError
}
@if (!string.IsNullOrEmpty(dumpSuccess) && dumpErrorDbId == db.Id)
{
@dumpSuccess
}
|
|||
|
@migrateError
}
@if (!string.IsNullOrEmpty(migrateSuccess) && migrateErrorDbId == db.Id)
{
@migrateSuccess
}
|
|||
|
@foreach (KeyValuePair
@cred.Key: @cred.Value
}
|
|||
|
@regPgDbActionError
|
|||
| Created | Size | Bucket | Actions |
|---|---|---|---|
| @dump.CreatedAt.ToString("yyyy-MM-dd HH:mm") | @FormatBytes(dump.SizeBytes) | @dump.StorageLink.Name |
|
|
@dumpRestoreError
}
@if (!string.IsNullOrEmpty(dumpRestoreSuccess) && dumpRestoreErrorDumpId == dump.Id)
{
@dumpRestoreSuccess
}
|
|||
Register a CloudNativePG cluster that is already running in Kubernetes. EntKube will read its configuration from the Cluster CRD and store the superuser credentials in vault. No Kubernetes resources are created or modified.
| Pod | Role | Status | Ready | Node | Age | Restarts |
|---|---|---|---|---|---|---|
| @pod.Name | @if (pod.Role == "primary") { Primary } else { Replica } | @if (pod.Status == "Running") { Running } else if (pod.Status == "Pending") { Pending } else { @pod.Status } | @if (pod.Ready) { } else { } | @(pod.Node ?? "—") | @FormatAge(pod.StartTime) | @if (pod.Restarts > 0) { @pod.Restarts } else { 0 } |
| Database | Owner | Status | Created | |||
|---|---|---|---|---|---|---|
| @cdb.Name | @cdb.Owner | @if (cdb.Status == CnpgDatabaseStatus.Ready) { Ready } else if (cdb.Status == CnpgDatabaseStatus.Creating) { Creating } else { @cdb.Status } | @cdb.CreatedAt.ToString("yyyy-MM-dd HH:mm") | @if (dbOwnershipOk.TryGetValue(cdb.Id, out bool ownerOk) && ownerOk) { } else { } | ||
|
Drop @cdb.Name? This drops the PostgreSQL database and removes all credentials.
|
||||||
|
@dbFixMessage
|
||||||
K8s Secret:
@($"{mc.Name}-{cdb.Name}-credentials") in namespace @mc.Namespace
|
||||||
No databases created yet. Use the button to add one.
} @* ── Backups ── *@| Name | Type | Status | Started | Completed | Size |
|---|---|---|---|---|---|
| @bk.Name | @if (bk.Type == CnpgBackupType.Scheduled) { Scheduled } else { On-Demand } | @if (bk.Status == CnpgBackupStatus.Completed) { Completed } else if (bk.Status == CnpgBackupStatus.Running) { Running } else { Failed } | @bk.StartedAt.ToString("yyyy-MM-dd HH:mm") | @(bk.CompletedAt?.ToString("HH:mm") ?? "—") | @(bk.SizeBytes.HasValue ? FormatBytes(bk.SizeBytes.Value) : "—") |
No backups yet. Click to create one.
} else {Backups are not configured. Assign an S3 bucket to enable backups.
} @* ── Backup Restore Panel (CNPG) ── *@ @if (selectedCnpgBackup != null && selectedCnpgBackupCluster?.Id == mc.Id) {pg_dump to export specific databases.
Register a database that already exists in this CNPG cluster. Click Discover to load the list of databases, or fill in the fields manually. Credentials are stored in vault — no SQL is executed.
Register a MongoDB cluster that was deployed outside EntKube. This creates a tracking record without modifying the live cluster.
Register a database that already exists in this external cluster. No MongoDB commands are run — this only creates a tracking record.
Copies all data from @mc.Name (via connection URI) to a managed Community Operator cluster using a direct dump-restore Job. The migration runs on the target cluster's Kubernetes environment. Existing data in the target is overwritten (mongorestore --drop).
@{ var managedMongoTargets = managedMongoClusters?.Where(c => !c.IsExternal).ToList() ?? []; } @if (managedMongoTargets.Count == 0) {| Pod | Status | Ready | Node | Age | Restarts |
|---|---|---|---|---|---|
| @pod.Name | @if (pod.Status == "Running") { Running } else if (pod.Status == "Pending") { Pending } else { @pod.Status } | @if (pod.Ready) { } else { } | @(pod.Node ?? "—") | @FormatAge(pod.StartTime) | @if (pod.Restarts > 0) { @pod.Restarts } else { 0 } |
| Database | Status | Created | |||
|---|---|---|---|---|---|
| @mdb.Name | @if (mdb.Status == MongoDatabaseStatus.Ready) { Ready } else if (mdb.Status == MongoDatabaseStatus.Creating) { Creating } else { @mdb.Status } | @mdb.CreatedAt.ToString("yyyy-MM-dd HH:mm") | @if (!mc.IsExternal) { } | ||
|
|||||
|
@mongoDbActionError
|
|||||
|
@mongoMigrateDbError
}
@if (!string.IsNullOrEmpty(mongoMigrateDbSuccess) && mongoMigrateDbId == mdb.Id)
{
@mongoMigrateDbSuccess
}
|
|||||
|
Delete @mdb.Name?
@if (mc.IsExternal)
{
}
|
|||||
No databases tracked yet. Use the button to track an existing database, or databases are discovered automatically if this cluster uses the MongoDB Community Operator.
} else {No databases created yet. Use the button to add one.
} @* ── Backups ── *@| Name | Type | Status | Started | Completed |
|---|---|---|---|---|
| @bk.Name | @if (bk.Type == MongoBackupType.Scheduled) { Scheduled } else { On-Demand } | @if (bk.Status == MongoBackupStatus.Completed) { Completed } else if (bk.Status == MongoBackupStatus.Running) { Running } else { Failed } | @bk.StartedAt.ToString("yyyy-MM-dd HH:mm") | @(bk.CompletedAt?.ToString("HH:mm") ?? "—") |
No backups yet. Click to create one.
} else if (mc.IsExternal) {Backups are not configured. Set an admin password and assign an S3 bucket via the settings button to enable backups.
} else {Backups are not configured. Assign an S3 bucket to enable backups.
} @* ── Backup Restore Panel (MongoDB) ── *@ @if (selectedMongoBackup != null && selectedMongoBackupCluster?.Id == mc.Id) {allowVolumeExpansion: true on the StorageClass. Can only grow, not shrink.spec.version in the existing MongoDBCommunity CRD. The Community Operator performs a rolling upgrade of replica set members.
Existing users, auth config, and StatefulSet settings are preserved.