added "update quickstack" button in settings

This commit is contained in:
biersoeckli
2024-11-25 17:48:55 +00:00
parent 0669464590
commit c7b3179a4a
4 changed files with 53 additions and 4 deletions

View File

@@ -5,7 +5,7 @@ import paramService, { ParamService } from "@/server/services/param.service";
import { QsIngressSettingsModel, qsIngressSettingsZodModel } from "@/model/qs-settings.model";
import { QsLetsEncryptSettingsModel, qsLetsEncryptSettingsZodModel } from "@/model/qs-letsencrypt-settings.model";
import quickStackService from "@/server/services/qs.service";
import { ServerActionResult } from "@/model/server-action-error-return.model";
import { ServerActionResult, SuccessActionResult } from "@/model/server-action-error-return.model";
export const updateIngressSettings = async (prevState: any, inputData: QsIngressSettingsModel) =>
saveFormAction(inputData, qsIngressSettingsZodModel, async (validatedData) => {
@@ -47,3 +47,10 @@ export const getConfiguredHostname: () => Promise<ServerActionResult<unknown, st
return await paramService.getString(ParamService.QS_SERVER_HOSTNAME);
});
export const updateQuickstack = async () =>
simpleAction(async () => {
await getAuthUserSession();
await quickStackService.updateQuickStack();
return new SuccessActionResult(undefined, 'QuickStack will be updated, refresh the page in a few seconds.');
});

View File

@@ -12,6 +12,7 @@ import userService from "@/server/services/user.service";
import paramService, { ParamService } from "@/server/services/param.service";
import QuickStackIngressSettings from "./qs-ingress-settings";
import QuickStackLetsEncryptSettings from "./qs-letsencrypt-settings";
import QuickStackMaintenanceSettings from "./qs-maintenance-settings";
export default async function ProjectPage() {
@@ -28,6 +29,7 @@ export default async function ProjectPage() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div><QuickStackIngressSettings disableNodePortAccess={disableNodePortAccess!} serverUrl={serverUrl!} /></div>
<div> <QuickStackLetsEncryptSettings letsEncryptMail={letsEncryptMail!} /></div>
<div><QuickStackMaintenanceSettings /></div>
</div>
</div>
)

View File

@@ -0,0 +1,32 @@
'use client';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { updateQuickstack } from "./actions";
import { Button } from "@/components/ui/button";
import { Toast } from "@/lib/toast.utils";
import { useConfirmDialog } from "@/lib/zustand.states";
export default function QuickStackMaintenanceSettings() {
const useConfirm = useConfirmDialog();
return <>
<Card>
<CardHeader>
<CardTitle>Maintenance</CardTitle>
</CardHeader>
<CardContent>
<Button variant="secondary" onClick={async () => {
if (await useConfirm.openDialog({
title: 'Update QuickStack',
description: 'This action will restart the QuickStack service and installs the lastest version. It may take a few minutes to complete.',
yesButton: "Update QuickStack",
})) {
Toast.fromAction(() => updateQuickstack());
}
}}>Update QuickStack</Button>
</CardContent>
</Card >
</>;
}

View File

@@ -15,6 +15,10 @@ class QuickStackService {
private readonly QUICKSTACK_SERVICEACCOUNT_NAME = 'qs-service-account';
private readonly CLUSTER_ISSUER_NAME = 'letsencrypt-production';
async updateQuickStack() {
const existingDeployment = await this.getExistingDeployment();
await this.createOrUpdateDeployment(existingDeployment.nextAuthHostname, existingDeployment.nextAuthSecret);
}
async initializeQuickStack() {
await namespaceService.createNamespaceIfNotExists(this.QUICKSTACK_NAMESPACE)
@@ -254,7 +258,7 @@ class QuickStackService {
}
}
async createOrUpdateDeployment(nextAuthHostname?: string, inputNextAuthSecret?: string) {
async createOrUpdateDeployment(nextAuthHostname?: string, inputNextAuthSecret?: string, imageTag = 'latest') {
const generatedNextAuthSecret = crypto.randomBytes(32).toString('base64');
const existingDeployment = await this.getExistingDeployment();
const body: V1Deployment = {
@@ -275,6 +279,9 @@ class QuickStackService {
metadata: {
labels: {
app: this.QUICKSTACK_DEPLOYMENT_NAME
},
annotations: {
deploymentTimestamp: new Date().getTime() + "",
}
},
spec: {
@@ -287,7 +294,7 @@ class QuickStackService {
containers: [
{
name: this.QUICKSTACK_DEPLOYMENT_NAME,
image: 'quickstack/quickstack:latest',
image: `quickstack/quickstack:${imageTag}`,
imagePullPolicy: 'Always',
env: [
{
@@ -346,7 +353,8 @@ class QuickStackService {
const allDeployments = await k3s.apps.listNamespacedDeployment(this.QUICKSTACK_NAMESPACE);
const existingDeployments = allDeployments.body.items.find(d => d.metadata!.name === this.QUICKSTACK_DEPLOYMENT_NAME);
const nextAuthSecret = existingDeployments?.spec?.template?.spec?.containers?.[0].env?.find(e => e.name === 'NEXTAUTH_SECRET')?.value;
return { existingDeployments, nextAuthSecret };
const nextAuthHostname = existingDeployments?.spec?.template?.spec?.containers?.[0].env?.find(e => e.name === 'NEXTAUTH_URL')?.value;
return { existingDeployments, nextAuthSecret, nextAuthHostname };
}
}