improve orchestrator, docker settings, and ui layouts

This commit is contained in:
Ishaan Dey
2024-05-12 22:06:11 -07:00
parent 18aca540cc
commit 59fb0521af
15 changed files with 264 additions and 128 deletions

View File

@ -22,7 +22,7 @@ spec:
image: ishaan1013/sandbox:latest
ports:
- containerPort: 4000
- containerPort: 3000
- containerPort: 8000
volumeMounts:
- name: workspace-volume
mountPath: /workspace
@ -54,8 +54,8 @@ spec:
targetPort: 4000
- protocol: TCP
name: user
port: 3000
targetPort: 3000
port: 8000
targetPort: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
@ -83,4 +83,4 @@ spec:
service:
name: <SANDBOX>
port:
number: 3000
number: 8000

View File

@ -19,9 +19,12 @@ app.use(express.json())
dotenv.config()
const corsOptions = {
origin: ['http://localhost:3000', 'https://s.ishaand.com', 'http://localhost:4000'],
origin: ['http://localhost:3000', 'https://s.ishaand.com', 'http://localhost:4000', /\.ws\.ishaand\.com$/],
}
// app.use(cors(corsOptions))
app.use(cors())
const kubeconfig = new KubeConfig()
if (process.env.NODE_ENV === "production") {
kubeconfig.loadFromOptions({
@ -110,25 +113,26 @@ const dataSchema = z.object({
sandboxId: z.string(),
})
const namespace = "sandbox"
const namespace = "ingress-nginx"
app.get("/test", cors(), async (req, res) => {
app.post("/test", async (req, res) => {
res.status(200).send({ message: "Orchestrator is up and running." })
})
app.get("/test/cors", cors(corsOptions), async (req, res) => {
res.status(200).send({ message: "With CORS, Orchestrator is up and running." })
})
app.post("/start", cors(corsOptions), async (req, res) => {
app.post("/start", async (req, res) => {
const { sandboxId } = dataSchema.parse(req.body)
try {
console.log("Creating resources for sandbox", sandboxId)
const kubeManifests = readAndParseKubeYaml(
path.join(__dirname, "../service.yaml"),
sandboxId
)
console.log("Successfully read and parsed kube yaml")
async function resourceExists(api: any, getMethod: string, name: string) {
try {
await api[getMethod](namespace, name)
@ -139,44 +143,57 @@ app.post("/start", cors(corsOptions), async (req, res) => {
}
}
kubeManifests.forEach(async (manifest) => {
const promises = kubeManifests.map(async (manifest) => {
const { kind, metadata: { name } } = manifest
if (kind === "Deployment")
if (!(await resourceExists(appsV1Api, 'readNamespacedDeployment', name))) {
await appsV1Api.createNamespacedDeployment(namespace, manifest)
console.log("Made deploymnet")
} else {
return res.status(200).send({ message: "Resource deployment already exists." })
}
else if (kind === "Service")
if (!(await resourceExists(coreV1Api, 'readNamespacedService', name))) {
await coreV1Api.createNamespacedService(namespace, manifest)
console.log("Made service")
} else {
return res.status(200).send({ message: "Resource service already exists." })
}
else if (kind === "Ingress")
if (!(await resourceExists(networkingV1Api, 'readNamespacedIngress', name))) {
await networkingV1Api.createNamespacedIngress(namespace, manifest)
console.log("Made ingress")
} else {
return res.status(200).send({ message: "Resource ingress already exists." })
}
})
await Promise.all(promises)
console.log("All done!")
res.status(200).send({ message: "Resources created." })
} catch (error) {
console.log("Failed to create resources", error)
} catch (error: any) {
const body = error.response.body
console.log("Failed to create resources", body)
if (body.code === 409) {
return res.status(200).send({ message: "Resource already exists." })
}
res.status(500).send({ message: "Failed to create resources." })
}
})
app.post("/stop", cors(corsOptions), async (req, res) => {
app.post("/stop", async (req, res) => {
const { sandboxId } = dataSchema.parse(req.body)
console.log("Deleting resources for sandbox", sandboxId)
try {
const kubeManifests = readAndParseKubeYaml(
path.join(__dirname, "../service.yaml"),
sandboxId
)
kubeManifests.forEach(async (manifest) => {
const promises = kubeManifests.map(async (manifest) => {
if (manifest.kind === "Deployment")
await appsV1Api.deleteNamespacedDeployment(
manifest.metadata?.name || "",
@ -193,6 +210,9 @@ app.post("/stop", cors(corsOptions), async (req, res) => {
namespace
)
})
await Promise.all(promises)
res.status(200).send({ message: "Resources deleted." })
} catch (error) {
console.log("Failed to delete resources", error)

View File

@ -1,2 +1,3 @@
.env
node_modules
projects

View File

@ -1,8 +1,10 @@
ARG CF_API_TOKEN
ARG CF_USER_ID
FROM node:20
# Security: Drop all capabilities
USER root
RUN apt-get update && apt-get install -y libcap2-bin
RUN setcap cap_net_bind_service=+ep /usr/local/bin/node
WORKDIR /code
COPY package*.json ./
@ -13,8 +15,15 @@ COPY . .
RUN npm run build
# Security: Create non-root user and assign ownership
RUN useradd -m myuser
RUN mkdir projects && chown -R myuser:myuser projects
USER myuser
EXPOSE 3000
ARG CF_API_TOKEN
ARG CF_USER_ID
ENV CF_API_TOKEN=$CF_API_TOKEN
ENV CF_USER_ID=$CF_USER_ID

View File

@ -435,15 +435,16 @@ io.on("connection", async (socket) => {
clearTimeout(inactivityTimeout)
};
if (sockets.length === 0) {
console.log("STARTING TIMER")
inactivityTimeout = setTimeout(() => {
io.fetchSockets().then(sockets => {
io.fetchSockets().then(async (sockets) => {
if (sockets.length === 0) {
// close server
console.log("Closing server due to inactivity.");
stopServer(data.sandboxId, data.userId)
// const res = await stopServer(data.sandboxId, data.userId)
}
});
}, 60000);
}, 20000);
}
})

View File

@ -198,7 +198,7 @@ ${code}`,
}
export const stopServer = async (sandboxId: string, userId: string) => {
await fetch("http://localhost:4001/stop", {
const res = await fetch("http://localhost:4001/stop", {
method: "POST",
headers: {
"Content-Type": "application/json",
@ -208,4 +208,7 @@ export const stopServer = async (sandboxId: string, userId: string) => {
userId
}),
})
const data = await res.json()
return data
}

View File

@ -55,6 +55,9 @@ import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
port: 8000,
},
})
`,
},