Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@aws-sdk/client-dynamodb": "^3.772.0",
"@aws-sdk/client-ec2": "^3.767.0",
"@aws-sdk/client-iam": "^3.758.0",
"@aws-sdk/client-service-quotas": "^3.792.0",
"@aws-sdk/client-ssm": "^3.774.0",
"@aws-sdk/lib-dynamodb": "^3.772.0",
"argon2": "^0.41.1",
Expand Down
16 changes: 11 additions & 5 deletions src/app/api/instanceTypes/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { NextResponse } from "next/server";
import { NextRequest, NextResponse } from "next/server";
import { getEC2InstanceTypes } from "@/utils/AWS/EC2/getEC2InstanceTypes";

export async function GET() {
export async function GET(request: NextRequest) {
try {
const instanceTypes = await getEC2InstanceTypes();
const searchParams = request.nextUrl.searchParams;
const architecture =
(searchParams.get("architecture") as "all" | "amd64" | "arm64") || "all";
const instanceTypes = await getEC2InstanceTypes(architecture);
return NextResponse.json({ instanceTypes });
} catch (error) {
console.error("API Error:", error);
return NextResponse.json({ message: "Internal Server Error" }, { status: 500 });
return NextResponse.json(
{ message: "Internal Server Error" },
{ status: 500 },
);
}
}
}
18 changes: 9 additions & 9 deletions src/app/api/instances/[name]/configuration/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import updateConfiguration from "./utils/updateConfiguration";

export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ name: string }> }
{ params }: { params: Promise<{ name: string }> },
) {
const searchParams = request.nextUrl.searchParams;
const region = searchParams.get("region");
Expand All @@ -17,7 +17,7 @@ export async function GET(
if (!region) {
return NextResponse.json(
{ message: "Missing region parameter" },
{ status: 400 }
{ status: 400 },
);
}

Expand All @@ -29,14 +29,14 @@ export async function GET(
console.error("Error fetching configuration:", error);
return NextResponse.json(
{ message: "Error fetching configuration", error: String(error) },
{ status: 500 }
{ status: 500 },
);
}
}

export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ name: string }> }
{ params }: { params: Promise<{ name: string }> },
) {
const searchParams = request.nextUrl.searchParams;
const region = searchParams.get("region");
Expand All @@ -45,7 +45,7 @@ export async function POST(
if (!region) {
return NextResponse.json(
{ message: "Missing region parameter" },
{ status: 400 }
{ status: 400 },
);
}

Expand All @@ -58,7 +58,7 @@ export async function POST(
console.error("Invalid configuration:", errors);
return NextResponse.json(
{ message: "Invalid configuration", errors },
{ status: 400 }
{ status: 400 },
);
}

Expand All @@ -72,9 +72,9 @@ export async function POST(
eventEmitter.emit("notification", {
type: "configuration",
status: "success",
instanceName: instanceName,
instanceName,

message: "Configuration updated successfully",
message: `Configuration for ${instanceName} updated successfully`,
});
deleteEvent(instanceName, "configuration");

Expand All @@ -91,7 +91,7 @@ export async function POST(
console.error("Error updating configuration:", error);
return NextResponse.json(
{ message: "Error updating configuration", error: String(error) },
{ status: 500 }
{ status: 500 },
);
}
}
16 changes: 8 additions & 8 deletions src/app/api/instances/[name]/plugins/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { deleteEvent } from "@/utils/eventBackups";

export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ name: string }> }
{ params }: { params: Promise<{ name: string }> },
) {
const searchParams = request.nextUrl.searchParams;
const region = searchParams.get("region");
Expand All @@ -20,7 +20,7 @@ export async function GET(
if (!region || !username || !password) {
return NextResponse.json(
{ message: "Missing parameters" },
{ status: 400 }
{ status: 400 },
);
}

Expand All @@ -37,14 +37,14 @@ export async function GET(
console.error("Error fetching plugins:", error);
return NextResponse.json(
{ message: "Error fetching plugins", error: String(error) },
{ status: 500 }
{ status: 500 },
);
}
}

export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ name: string }> }
{ params }: { params: Promise<{ name: string }> },
) {
const searchParams = request.nextUrl.searchParams;
const region = searchParams.get("region");
Expand All @@ -53,7 +53,7 @@ export async function POST(
if (!region) {
return NextResponse.json(
{ message: "Missing region parameter" },
{ status: 400 }
{ status: 400 },
);
}

Expand All @@ -73,8 +73,8 @@ export async function POST(
eventEmitter.emit("notification", {
type: "plugin",
status: "success",
instanceName: instanceName,
message: `${enabled ? "Enabled" : "Disabled"} ${name}`,
instanceName,
message: `${enabled ? "Enabled" : "Disabled"} ${name} on ${instanceName}`,
});

deleteEvent(instanceName, "plugin");
Expand All @@ -93,7 +93,7 @@ export async function POST(
console.error("Error updating plugins:", error);
return NextResponse.json(
{ message: "Error updating plugins", error: String(error) },
{ status: 500 }
{ status: 500 },
);
}
}
46 changes: 34 additions & 12 deletions src/app/instances/[name]/hardware/components/InstanceTypePage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"use client";

import { useInstanceContext } from "../../InstanceContext";
import { useNotificationsContext } from "@/app/NotificationContext";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import axios from "axios";
import ErrorBanner from "@/app/instances/components/ErrorBanner";
Expand All @@ -10,8 +12,9 @@ type InstanceTypes = Record<string, string[]>;

export function InstanceTypePage() {
const [instanceTypes, setInstanceTypes] = useState<InstanceTypes>({});
const { addNotification, formPending } = useNotificationsContext();
const { instance } = useInstanceContext();
const [saving, setSaving] = useState(false);
const router = useRouter();
const [isLoading, setIsLoading] = useState(true);
const [selectedInstanceType, setSelectedInstanceType] = useState("");
const [filteredInstanceTypes, setFilteredInstanceTypes] = useState<string[]>(
Expand All @@ -23,7 +26,10 @@ export function InstanceTypePage() {
useEffect(() => {
const fetchInstanceTypes = async () => {
try {
const { data } = await axios.get("/api/instanceTypes");
const architecture = instance?.type.includes("t2") ? "amd64" : "arm64";
const { data } = await axios.get(
`/api/instanceTypes?architecture=${architecture}`,
);
setIsLoading(false);
setInstanceTypes(data.instanceTypes);
} catch (error) {
Expand All @@ -32,7 +38,7 @@ export function InstanceTypePage() {
};

fetchInstanceTypes();
}, []);
}, [instance?.type]);

useEffect(() => {
setFilteredInstanceTypes(instanceTypes[selectedInstanceType] ?? []);
Expand Down Expand Up @@ -62,20 +68,32 @@ export function InstanceTypePage() {
const updateHardware = async () => {
const validationErrors = validateInstanceTypeAndSize();
if (validationErrors.length > 0) {
setSaving(false);
return false;
}

if (!instance?.name) {
return false;
}

try {
await addNotification({
type: "instanceType",
status: "pending",
instanceName: instance?.name,
path: "instances",
message: `Updating type of ${instance?.name} to ${instanceSize}`,
});

await axios.put(`/api/instances/${instance?.name}/hardware/type`, {
instanceId: instance?.id,
instanceType: instanceSize,
region: instance?.region,
instanceName: instance?.name,
});
return true;
} catch (error) {
console.log(error);
if (!error) return;
setSaving(false);
setErrors([
"Failed to update instance hardware. You must be upgrading the size.",
]);
Expand Down Expand Up @@ -120,6 +138,10 @@ export function InstanceTypePage() {
size. Changing this will cause the instance to be taken down and
re-deployed on the new hardware - this can take a couple minutes.
</p>
<p className="font-text1 text-sm mb-6 text-red-400">
Changing this will cause an instance restart - sending you to the home
page.
</p>

{errors.length > 0 && (
<div className="mb-4">
Expand Down Expand Up @@ -147,7 +169,7 @@ export function InstanceTypePage() {
</div>
</div>
) : (
<fieldset disabled={saving} className="space-y-4">
<fieldset disabled={formPending()} className="space-y-4">
<div className="flex items-center gap-4">
<label
htmlFor="instanceType"
Expand Down Expand Up @@ -197,19 +219,19 @@ export function InstanceTypePage() {
<div className="font-heading1 text-sm flex justify-end gap-4 mt-6">
<button
className={`font-heading1 px-4 py-2 text-mainbg1 font-semibold rounded-sm
${saving ? "bg-btnhover1 opacity-70 cursor-not-allowed" : "px-4 py-2 bg-btn1 hover:bg-btnhover1 text-mainbg1 font-semibold rounded-sm flex items-center justify-center hover:shadow-[0_0_10px_#87d9da] transition-all duration-200"}
${formPending() ? "bg-btnhover1 opacity-70 cursor-not-allowed" : "px-4 py-2 bg-btn1 hover:bg-btnhover1 text-mainbg1 font-semibold rounded-sm flex items-center justify-center hover:shadow-[0_0_10px_#87d9da] transition-all duration-200"}
`}
type="submit"
disabled={saving}
disabled={formPending()}
onClick={async (e) => {
e.preventDefault();
setSaving(true);
const success = await updateHardware();
if (success)
window.location.href = `/instances/${instance?.name}/hardware?region=${instance?.region}`;
if (success) {
router.push(`/instances`);
}
}}
>
{saving ? (
{formPending() ? (
<span className="flex items-center gap-2">
<SubmissionSpinner />
Updating Instance ...
Expand Down
13 changes: 9 additions & 4 deletions src/app/instances/[name]/hardware/components/StoragePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ export function StoragePage() {
The total amount of storage the broker has access to. Must be expanded -
cannot be downsized. System files take about 4gb of this total.
</p>
<p className="font-text1 text-sm mb-6 text-red-400">
Changing this will cause an instance restart - sending you to the home
page.
</p>
<StorageDetails />

{errors.length > 0 && (
Expand Down Expand Up @@ -166,10 +170,11 @@ export function StoragePage() {
<div className="font-heading1 text-sm flex justify-end gap-4">
<button
className={`font-heading1 px-4 py-2 text-mainbg1 font-semibold rounded-sm
${formPending()
? "bg-btnhover1 opacity-70 cursor-not-allowed"
: "px-4 py-2 bg-btn1 hover:bg-btnhover1 text-mainbg1 font-semibold rounded-sm flex items-center justify-center hover:shadow-[0_0_10px_#87d9da] transition-all duration-200"
}
${
formPending()
? "bg-btnhover1 opacity-70 cursor-not-allowed"
: "px-4 py-2 bg-btn1 hover:bg-btnhover1 text-mainbg1 font-semibold rounded-sm flex items-center justify-center hover:shadow-[0_0_10px_#87d9da] transition-all duration-200"
}
`}
disabled={formPending()}
onClick={async (e) => {
Expand Down
Loading