feat: add configurable VPS provider API URLs for emulator testing
- Add LINODE_API_URL and VULTR_API_URL environment variables - Update LinodeProvider and VultrProvider to accept optional baseUrl - Update ProvisioningService to pass API URLs to providers - Add source_provider and source_region_code to PricingWithProvider type - Use source_provider (linode/vultr) instead of provider_name (Anvil) - Improve error handling for non-JSON responses in LinodeProvider Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -114,7 +114,9 @@ export async function handleProvision(
|
|||||||
env.DB, // cloud-instances-db
|
env.DB, // cloud-instances-db
|
||||||
env.USER_DB, // telegram-conversations
|
env.USER_DB, // telegram-conversations
|
||||||
env.LINODE_API_KEY,
|
env.LINODE_API_KEY,
|
||||||
env.VULTR_API_KEY
|
env.VULTR_API_KEY,
|
||||||
|
env.LINODE_API_URL,
|
||||||
|
env.VULTR_API_URL
|
||||||
);
|
);
|
||||||
|
|
||||||
// Provision server
|
// Provision server
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ export async function handleProvisionQueue(
|
|||||||
env.DB,
|
env.DB,
|
||||||
env.USER_DB,
|
env.USER_DB,
|
||||||
env.LINODE_API_KEY,
|
env.LINODE_API_KEY,
|
||||||
env.VULTR_API_KEY
|
env.VULTR_API_KEY,
|
||||||
|
env.LINODE_API_URL,
|
||||||
|
env.VULTR_API_URL
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const message of batch.messages) {
|
for (const message of batch.messages) {
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ interface LinodeError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LinodeProvider extends VPSProviderBase {
|
export class LinodeProvider extends VPSProviderBase {
|
||||||
constructor(apiKey: string, timeout: number = 30000) {
|
static readonly DEFAULT_BASE_URL = 'https://api.linode.com/v4';
|
||||||
|
|
||||||
|
constructor(apiKey: string, baseUrl?: string, timeout: number = 30000) {
|
||||||
super({
|
super({
|
||||||
apiKey,
|
apiKey,
|
||||||
baseUrl: 'https://api.linode.com/v4',
|
baseUrl: baseUrl || LinodeProvider.DEFAULT_BASE_URL,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -58,18 +60,32 @@ export class LinodeProvider extends VPSProviderBase {
|
|||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Read response text first to handle both JSON and HTML errors
|
||||||
|
const responseText = await response.text();
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const error = (await response.json()) as LinodeError;
|
// Try to parse as JSON, but handle HTML responses gracefully
|
||||||
return {
|
try {
|
||||||
success: false,
|
const error = JSON.parse(responseText) as LinodeError;
|
||||||
error: {
|
return {
|
||||||
code: `LINODE_${response.status}`,
|
success: false,
|
||||||
message: error.errors?.[0]?.reason || 'Unknown error',
|
error: {
|
||||||
},
|
code: `LINODE_${response.status}`,
|
||||||
};
|
message: error.errors?.[0]?.reason || 'Unknown error',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
code: `LINODE_${response.status}`,
|
||||||
|
message: `Non-JSON response: ${responseText.substring(0, 200)}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = (await response.json()) as LinodeInstance;
|
const data = JSON.parse(responseText) as LinodeInstance;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ export class ProvisioningService {
|
|||||||
db: D1Database, // cloud-instances-db: pricing, providers
|
db: D1Database, // cloud-instances-db: pricing, providers
|
||||||
userDb: D1Database, // telegram-conversations: users, deposits, orders
|
userDb: D1Database, // telegram-conversations: users, deposits, orders
|
||||||
linodeApiKey?: string,
|
linodeApiKey?: string,
|
||||||
vultrApiKey?: string
|
vultrApiKey?: string,
|
||||||
|
linodeApiUrl?: string, // Optional: for testing with emulator
|
||||||
|
vultrApiUrl?: string // Optional: for testing with emulator
|
||||||
) {
|
) {
|
||||||
this.env = env;
|
this.env = env;
|
||||||
this.repo = new ProvisioningRepository(db, userDb);
|
this.repo = new ProvisioningRepository(db, userDb);
|
||||||
this.linodeProvider = linodeApiKey ? new LinodeProvider(linodeApiKey) : null;
|
this.linodeProvider = linodeApiKey ? new LinodeProvider(linodeApiKey, linodeApiUrl) : null;
|
||||||
this.vultrProvider = vultrApiKey ? new VultrProvider(vultrApiKey) : null;
|
this.vultrProvider = vultrApiKey ? new VultrProvider(vultrApiKey, vultrApiUrl) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,10 +36,12 @@ interface VultrError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class VultrProvider extends VPSProviderBase {
|
export class VultrProvider extends VPSProviderBase {
|
||||||
constructor(apiKey: string, timeout: number = 30000) {
|
static readonly DEFAULT_BASE_URL = 'https://api.vultr.com/v2';
|
||||||
|
|
||||||
|
constructor(apiKey: string, baseUrl?: string, timeout: number = 30000) {
|
||||||
super({
|
super({
|
||||||
apiKey,
|
apiKey,
|
||||||
baseUrl: 'https://api.vultr.com/v2',
|
baseUrl: baseUrl || VultrProvider.DEFAULT_BASE_URL,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ export interface Env {
|
|||||||
// VPS Provider API Keys
|
// VPS Provider API Keys
|
||||||
LINODE_API_KEY?: string;
|
LINODE_API_KEY?: string;
|
||||||
VULTR_API_KEY?: string;
|
VULTR_API_KEY?: string;
|
||||||
|
// VPS Provider API URLs (for testing with emulators)
|
||||||
|
LINODE_API_URL?: string; // Default: https://api.linode.com/v4
|
||||||
|
VULTR_API_URL?: string; // Default: https://api.vultr.com/v2
|
||||||
// Provision API security
|
// Provision API security
|
||||||
PROVISION_API_KEY?: string; // Required for /api/provision/* endpoints
|
PROVISION_API_KEY?: string; // Required for /api/provision/* endpoints
|
||||||
// Queue for async provisioning
|
// Queue for async provisioning
|
||||||
|
|||||||
@@ -39,3 +39,9 @@ queue = "provision-queue"
|
|||||||
max_batch_size = 1
|
max_batch_size = 1
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
dead_letter_queue = "provision-queue-dlq"
|
dead_letter_queue = "provision-queue-dlq"
|
||||||
|
|
||||||
|
# VPS Provider API URLs (for testing with emulators)
|
||||||
|
# Comment out or remove for production to use default URLs
|
||||||
|
[vars]
|
||||||
|
LINODE_API_URL = "https://linode.actions.it.com/v4"
|
||||||
|
VULTR_API_URL = "https://vultr.actions.it.com/v2"
|
||||||
|
|||||||
Reference in New Issue
Block a user