diff --git a/src/app/settings/server/actions.ts b/src/app/settings/server/actions.ts index c7e1653..a37102f 100644 --- a/src/app/settings/server/actions.ts +++ b/src/app/settings/server/actions.ts @@ -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 + simpleAction(async () => { + await getAuthUserSession(); + await quickStackService.updateQuickStack(); + return new SuccessActionResult(undefined, 'QuickStack will be updated, refresh the page in a few seconds.'); + }); diff --git a/src/app/settings/server/page.tsx b/src/app/settings/server/page.tsx index 046f251..1625ea0 100644 --- a/src/app/settings/server/page.tsx +++ b/src/app/settings/server/page.tsx @@ -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() {
+
) diff --git a/src/app/settings/server/qs-maintenance-settings.tsx b/src/app/settings/server/qs-maintenance-settings.tsx new file mode 100644 index 0000000..427e96b --- /dev/null +++ b/src/app/settings/server/qs-maintenance-settings.tsx @@ -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 <> + + + Maintenance + + + + + + + ; +} \ No newline at end of file diff --git a/src/server/services/qs.service.ts b/src/server/services/qs.service.ts index 5ba5da6..2357567 100644 --- a/src/server/services/qs.service.ts +++ b/src/server/services/qs.service.ts @@ -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 }; } }