milestone 32: task-shaped configuration, file mode as a rendering, config status api
Gates / frontend (push) Successful in 1m22s
Gates / test (push) Successful in 1m54s
Gates / test-aarch64 (push) Successful in 7m57s
Gates / package (push) Successful in 5m29s
Gates / container (push) Successful in 10s
CI / gates (push) Successful in 32m51s
Gates / frontend (push) Successful in 1m22s
Gates / test (push) Successful in 1m54s
Gates / test-aarch64 (push) Successful in 7m57s
Gates / package (push) Successful in 5m29s
Gates / container (push) Successful in 10s
CI / gates (push) Successful in 32m51s
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import * as stylex from "@stylexjs/stylex";
|
||||
import InlineError from "@/lib/InlineError";
|
||||
import { reloadCerts } from "@/lib/api";
|
||||
import type { CertReloadOutcome, CertsReload } from "@/lib/types";
|
||||
import { styles as shared } from "@/ui/styles";
|
||||
import { styles } from "./styles";
|
||||
|
||||
function describe(name: string, outcome: CertReloadOutcome): string {
|
||||
if (!outcome.enabled) return `${name}: not enabled`;
|
||||
if (outcome.reloaded) return `${name}: reloaded`;
|
||||
return `${name}: failed — ${outcome.error ?? "no reason given"}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* A runtime action, not a configuration write: it re-reads the certificate
|
||||
* files the running listeners already point at, so it stays enabled under
|
||||
* every authority — including a file-managed process, where renewing a
|
||||
* certificate is exactly the job that must not need a restart.
|
||||
*
|
||||
* The endpoint answers 200 even when a reload fails, per endpoint, because a
|
||||
* failed reload leaves the previous certificate serving. So the outcome is
|
||||
* rendered as a result, and only a transport or auth failure is an error.
|
||||
*/
|
||||
export default function ReloadCertsAction() {
|
||||
const mutation = useMutation<CertsReload>({ mutationFn: reloadCerts });
|
||||
const result = mutation.data;
|
||||
|
||||
return (
|
||||
<div {...stylex.props(styles.actionRow)}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => mutation.mutate()}
|
||||
disabled={mutation.isPending}
|
||||
{...stylex.props(shared.button, shared.focusRing)}
|
||||
>
|
||||
{mutation.isPending ? "Reloading certificates…" : "Reload certificates"}
|
||||
</button>
|
||||
{result !== undefined && (
|
||||
<p role="status" {...stylex.props(styles.success)}>
|
||||
{describe("DoH", result.doh)}. {describe("DoT", result.dot)}.
|
||||
</p>
|
||||
)}
|
||||
<InlineError error={mutation.error} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user