feat: manage OS images in database instead of hardcoded values

- Add os_images table with linode_image_id and vultr_os_id columns
- Support Ubuntu (24.04, 22.04), Debian (11-13), AlmaLinux (8-9),
  Rocky Linux (8-9), and Fedora 42
- AlmaLinux and Rocky Linux added as CentOS migration alternatives
- Default OS changed from ubuntu_22_04 to ubuntu_24_04
- Fix Vultr OS IDs (1743=22.04, 2284=24.04)
- Remove hardcoded OS validation, validate against DB
- Return available OS list in error message for invalid image

Migration: migrations/003_os_images.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-28 10:31:14 +09:00
parent 7d9edc14a3
commit 3c420d2841
5 changed files with 164 additions and 11 deletions

View File

@@ -5,7 +5,7 @@
* - USER_DB (telegram-conversations): users, deposits, orders
*/
import type { TelegramUser, UserDeposit, ServerOrder, PricingWithProvider } from '../types';
import type { TelegramUser, UserDeposit, ServerOrder, PricingWithProvider, OsImage } from '../types';
export class ProvisioningRepository {
constructor(
@@ -276,4 +276,58 @@ export class ProvisioningRepository {
await this.refundBalance(userId, amount);
await this.updateOrderStatus(orderId, 'failed', errorMessage);
}
// ============================================
// OS Image Operations (cloud-instances-db.os_images)
// ============================================
/**
* Get all active OS images
*/
async getActiveOsImages(): Promise<OsImage[]> {
const result = await this.db
.prepare(
`SELECT * FROM os_images
WHERE active = 1
ORDER BY sort_order`
)
.all();
return result.results as unknown as OsImage[];
}
/**
* Get OS image by key
*/
async getOsImageByKey(key: string): Promise<OsImage | null> {
const result = await this.db
.prepare('SELECT * FROM os_images WHERE key = ? AND active = 1')
.bind(key)
.first();
return result as unknown as OsImage | null;
}
/**
* Get default OS image
*/
async getDefaultOsImage(): Promise<OsImage | null> {
const result = await this.db
.prepare('SELECT * FROM os_images WHERE is_default = 1 AND active = 1')
.first();
return result as unknown as OsImage | null;
}
/**
* Validate OS image key exists and is active
*/
async isValidOsImage(key: string): Promise<boolean> {
const result = await this.db
.prepare('SELECT 1 FROM os_images WHERE key = ? AND active = 1')
.bind(key)
.first();
return result !== null;
}
}