mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-15 00:15:17 +00:00
feat(traefik): add option to skip YAML validation for Go templating
- Introduced a checkbox to skip YAML validation in both the UpdateTraefikConfig and ShowTraefikFile components, allowing users to save configurations that utilize Go templating. - Updated the onSubmit logic to conditionally validate YAML based on the new checkbox state, enhancing flexibility for users working with dynamic configurations.
This commit is contained in:
+35
-8
@@ -24,6 +24,8 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
const UpdateTraefikConfigSchema = z.object({
|
const UpdateTraefikConfigSchema = z.object({
|
||||||
@@ -59,6 +61,7 @@ export const validateAndFormatYAML = (yamlText: string) => {
|
|||||||
|
|
||||||
export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [skipYamlValidation, setSkipYamlValidation] = useState(false);
|
||||||
const { data, refetch } = api.application.readTraefikConfig.useQuery(
|
const { data, refetch } = api.application.readTraefikConfig.useQuery(
|
||||||
{
|
{
|
||||||
applicationId,
|
applicationId,
|
||||||
@@ -85,13 +88,15 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const onSubmit = async (data: UpdateTraefikConfig) => {
|
const onSubmit = async (data: UpdateTraefikConfig) => {
|
||||||
const { valid, error } = validateAndFormatYAML(data.traefikConfig);
|
if (!skipYamlValidation) {
|
||||||
if (!valid) {
|
const { valid, error } = validateAndFormatYAML(data.traefikConfig);
|
||||||
form.setError("traefikConfig", {
|
if (!valid) {
|
||||||
type: "manual",
|
form.setError("traefikConfig", {
|
||||||
message: (error as string) || "Invalid YAML",
|
type: "manual",
|
||||||
});
|
message: (error as string) || "Invalid YAML",
|
||||||
return;
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
form.clearErrors("traefikConfig");
|
form.clearErrors("traefikConfig");
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
@@ -116,6 +121,7 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
|||||||
setOpen(open);
|
setOpen(open);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
form.reset();
|
form.reset();
|
||||||
|
setSkipYamlValidation(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -169,7 +175,28 @@ routers:
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter className="flex-col sm:flex-row gap-4">
|
||||||
|
<div className="flex flex-col gap-1 w-full sm:w-auto sm:mr-auto">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="skip-yaml-validation-app"
|
||||||
|
checked={skipYamlValidation}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
setSkipYamlValidation(checked === true)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
htmlFor="skip-yaml-validation-app"
|
||||||
|
className="text-sm font-normal cursor-pointer"
|
||||||
|
>
|
||||||
|
Skip YAML validation (for Go templating)
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Check to save configs with Go templating (e.g.{" "}
|
||||||
|
<code className="text-xs">{"{{range}}"}</code>).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
form="hook-form-update-traefik-config"
|
form="hook-form-update-traefik-config"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CodeEditor } from "@/components/shared/code-editor";
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@@ -16,6 +17,7 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config";
|
import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config";
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ export const ShowTraefikFile = ({ path, serverId }: Props) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
const [canEdit, setCanEdit] = useState(true);
|
const [canEdit, setCanEdit] = useState(true);
|
||||||
|
const [skipYamlValidation, setSkipYamlValidation] = useState(false);
|
||||||
|
|
||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading, error, isError } =
|
||||||
api.settings.updateTraefikFile.useMutation();
|
api.settings.updateTraefikFile.useMutation();
|
||||||
@@ -66,13 +69,15 @@ export const ShowTraefikFile = ({ path, serverId }: Props) => {
|
|||||||
}, [form, form.reset, data]);
|
}, [form, form.reset, data]);
|
||||||
|
|
||||||
const onSubmit = async (data: UpdateServerMiddlewareConfig) => {
|
const onSubmit = async (data: UpdateServerMiddlewareConfig) => {
|
||||||
const { valid, error } = validateAndFormatYAML(data.traefikConfig);
|
if (!skipYamlValidation) {
|
||||||
if (!valid) {
|
const { valid, error } = validateAndFormatYAML(data.traefikConfig);
|
||||||
form.setError("traefikConfig", {
|
if (!valid) {
|
||||||
type: "manual",
|
form.setError("traefikConfig", {
|
||||||
message: error || "Invalid YAML",
|
type: "manual",
|
||||||
});
|
message: error || "Invalid YAML",
|
||||||
return;
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
form.clearErrors("traefikConfig");
|
form.clearErrors("traefikConfig");
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
@@ -153,14 +158,37 @@ routers:
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end">
|
<div className="flex flex-col gap-4">
|
||||||
<Button
|
<div className="flex items-center space-x-2">
|
||||||
isLoading={isLoading}
|
<Checkbox
|
||||||
disabled={canEdit || isLoading}
|
id="skip-yaml-validation"
|
||||||
type="submit"
|
checked={skipYamlValidation}
|
||||||
>
|
onCheckedChange={(checked) =>
|
||||||
Update
|
setSkipYamlValidation(checked === true)
|
||||||
</Button>
|
}
|
||||||
|
/>
|
||||||
|
<Label
|
||||||
|
htmlFor="skip-yaml-validation"
|
||||||
|
className="text-sm font-normal cursor-pointer"
|
||||||
|
>
|
||||||
|
Skip YAML validation (for Go templating)
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-muted-foreground -mt-2">
|
||||||
|
Traefik supports Go templating in dynamic configs (e.g.{" "}
|
||||||
|
<code className="text-xs">{"{{range}}"}</code>). Configs using
|
||||||
|
templates will fail standard YAML validation. Check this to save
|
||||||
|
without validation.
|
||||||
|
</p>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button
|
||||||
|
isLoading={isLoading}
|
||||||
|
disabled={canEdit || isLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
Reference in New Issue
Block a user