140 lines
3.7 KiB
TypeScript
140 lines
3.7 KiB
TypeScript
import config from "../config.ts";
|
|
import axios from "axios";
|
|
import { VMManager, type VM } from "./base.ts";
|
|
|
|
const DO_TOKEN = config.DO_TOKEN;
|
|
const region = "sfo3";
|
|
const gatewayHost = config.DO_GATEWAY;
|
|
const sshKeys = config.DO_SSH_KEYS.split(",");
|
|
|
|
export class DigitalOcean extends VMManager {
|
|
size = "s-2vcpu-2gb"; // s-1vcpu-1gb, s-1vcpu-2gb, s-2vcpu-2gb, s-2vcpu-4gb, c-2, s-4vcpu-8gb
|
|
largeSize = "s-4vcpu-8gb";
|
|
minRetries = 5;
|
|
reuseVMs = true;
|
|
id = "DO";
|
|
imageId = config.DO_IMAGE;
|
|
startVM = async (name: string) => {
|
|
const response = await axios({
|
|
method: "POST",
|
|
url: `https://api.digitalocean.com/v2/droplets`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
data: {
|
|
name: name,
|
|
region: region,
|
|
size: this.isLarge ? this.largeSize : this.size,
|
|
image: Number(this.imageId),
|
|
ssh_keys: sshKeys,
|
|
private_networking: true,
|
|
// user_data: cloudInit(),
|
|
tags: [this.getTag()],
|
|
},
|
|
});
|
|
const id = response.data.droplet.id;
|
|
return id;
|
|
};
|
|
|
|
terminateVM = async (id: string) => {
|
|
const response = await axios({
|
|
method: "DELETE",
|
|
url: `https://api.digitalocean.com/v2/droplets/${id}`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
};
|
|
|
|
rebootVM = async (id: string) => {
|
|
// Reboot the VM
|
|
const response2 = await axios({
|
|
method: "POST",
|
|
url: `https://api.digitalocean.com/v2/droplets/${id}/actions`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
data: {
|
|
type: "reboot",
|
|
},
|
|
});
|
|
return;
|
|
};
|
|
|
|
reimageVM = async (id: string) => {
|
|
// Rebuild the VM
|
|
const response2 = await axios({
|
|
method: "POST",
|
|
url: `https://api.digitalocean.com/v2/droplets/${id}/actions`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
data: {
|
|
type: "rebuild",
|
|
image: Number(this.imageId),
|
|
},
|
|
});
|
|
return;
|
|
};
|
|
|
|
getVM = async (id: string) => {
|
|
const response = await axios({
|
|
method: "GET",
|
|
url: `https://api.digitalocean.com/v2/droplets/${id}`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
let server = this.mapServerObject(response.data.droplet);
|
|
return server;
|
|
};
|
|
|
|
listVMs = async (filter: string) => {
|
|
// console.log(filter, tags);
|
|
const response = await axios({
|
|
method: "GET",
|
|
url: `https://api.digitalocean.com/v2/droplets`,
|
|
headers: {
|
|
Authorization: "Bearer " + DO_TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
params: {
|
|
// TODO need to update if over 100 results
|
|
per_page: 100,
|
|
tag_name: filter,
|
|
},
|
|
});
|
|
return response.data.droplets.map(this.mapServerObject);
|
|
};
|
|
|
|
powerOn = async (_id: string) => {};
|
|
|
|
attachToNetwork = async (_id: string) => {};
|
|
|
|
updateSnapshot = async () => {
|
|
return "";
|
|
};
|
|
|
|
mapServerObject = (server: any): VM => {
|
|
// const ip = server.networks.v4.find(
|
|
// (network: any) => network.type === 'private',
|
|
// )?.ip_address;
|
|
const ip = server.networks.v4.find(
|
|
(network: any) => network.type === "public",
|
|
)?.ip_address;
|
|
return {
|
|
id: server.id?.toString(),
|
|
// The gateway handles SSL termination and proxies to the private IP
|
|
host: ip ? `${gatewayHost}/?ip=${ip}` : "",
|
|
provider: this.id,
|
|
large: this.isLarge,
|
|
region: this.region,
|
|
};
|
|
};
|
|
}
|