feat: add server lifecycle management and D1 logging
- Add start/stop/reboot endpoints for server power management - Add D1-based logging system (logs table + db-logger utility) - Add idempotency_key validation for order deduplication - Extend VPS provider interface with lifecycle methods Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -134,9 +134,99 @@ export class LinodeProvider extends VPSProviderBase {
|
||||
}
|
||||
}
|
||||
|
||||
async startServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
|
||||
const url = `${this.config.baseUrl}/linode/instances/${instanceId}/boot`;
|
||||
|
||||
try {
|
||||
const response = await this.fetchWithRetry(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.config.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = (await response.json()) as LinodeError;
|
||||
return {
|
||||
success: false,
|
||||
error: error.errors?.[0]?.reason || 'Failed to start instance',
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Network error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async stopServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
|
||||
const url = `${this.config.baseUrl}/linode/instances/${instanceId}/shutdown`;
|
||||
|
||||
try {
|
||||
const response = await this.fetchWithRetry(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.config.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = (await response.json()) as LinodeError;
|
||||
return {
|
||||
success: false,
|
||||
error: error.errors?.[0]?.reason || 'Failed to stop instance',
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Network error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async rebootServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
|
||||
const url = `${this.config.baseUrl}/linode/instances/${instanceId}/reboot`;
|
||||
|
||||
try {
|
||||
const response = await this.fetchWithRetry(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.config.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = (await response.json()) as LinodeError;
|
||||
return {
|
||||
success: false,
|
||||
error: error.errors?.[0]?.reason || 'Failed to reboot instance',
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Network error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async getServerStatus(
|
||||
instanceId: string
|
||||
): Promise<{ status: string; ipv4?: string; ipv6?: string }> {
|
||||
): Promise<{ status: string; power_status?: string; ipv4?: string; ipv6?: string }> {
|
||||
const url = `${this.config.baseUrl}/linode/instances/${instanceId}`;
|
||||
|
||||
try {
|
||||
@@ -152,8 +242,10 @@ export class LinodeProvider extends VPSProviderBase {
|
||||
}
|
||||
|
||||
const data = (await response.json()) as LinodeInstance;
|
||||
// Linode: status is the power state (running, offline, etc.)
|
||||
return {
|
||||
status: data.status,
|
||||
power_status: data.status, // For compatibility with Vultr logic
|
||||
ipv4: data.ipv4?.[0],
|
||||
ipv6: data.ipv6?.split('/')[0],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user