mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-26 22:11:20 -07:00
Enhancement: widget support for Pulse v6 API changes (#6987)
Lint / Linting Checks (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Release Drafter / Auto Label PR (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Lint / Linting Checks (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Release Drafter / Auto Label PR (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
This commit is contained in:
@@ -12,5 +12,6 @@ widget:
|
|||||||
type: pulse
|
type: pulse
|
||||||
url: http://pulse.host.or.ip:7655
|
url: http://pulse.host.or.ip:7655
|
||||||
key: your-api-token # `monitoring:read` scope is required
|
key: your-api-token # `monitoring:read` scope is required
|
||||||
|
version: 2 # required for Pulse v6, defaults to 1
|
||||||
fields: ["nodes", "vms", "lxcs"] # optional
|
fields: ["nodes", "vms", "lxcs"] # optional
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -589,6 +589,7 @@ export function cleanServiceGroups(groups) {
|
|||||||
"grafana",
|
"grafana",
|
||||||
"gluetun",
|
"gluetun",
|
||||||
"vikunja",
|
"vikunja",
|
||||||
|
"pulse",
|
||||||
].includes(type)
|
].includes(type)
|
||||||
) {
|
) {
|
||||||
widget.version = parseVersionForUrl(version);
|
widget.version = parseVersionForUrl(version);
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ describe("utils/config/service-helpers", () => {
|
|||||||
widgets: [
|
widgets: [
|
||||||
{ type: "azuredevops", userEmail: "u@example.com", repositoryId: "r" },
|
{ type: "azuredevops", userEmail: "u@example.com", repositoryId: "r" },
|
||||||
{ type: "beszel", version: "2", systemId: "sys" },
|
{ type: "beszel", version: "2", systemId: "sys" },
|
||||||
|
{ type: "pulse", version: "2" },
|
||||||
{ type: "coinmarketcap", currency: "USD", symbols: "BTC", slugs: "bitcoin", defaultinterval: "1d" },
|
{ type: "coinmarketcap", currency: "USD", symbols: "BTC", slugs: "bitcoin", defaultinterval: "1d" },
|
||||||
{ type: "crowdsec", limit24h: "true" },
|
{ type: "crowdsec", limit24h: "true" },
|
||||||
{ type: "docker", server: "docker-local", container: "c1" },
|
{ type: "docker", server: "docker-local", container: "c1" },
|
||||||
@@ -345,6 +346,7 @@ describe("utils/config/service-helpers", () => {
|
|||||||
expect.objectContaining({ userEmail: "u@example.com", repositoryId: "r" }),
|
expect.objectContaining({ userEmail: "u@example.com", repositoryId: "r" }),
|
||||||
);
|
);
|
||||||
expect(widgets.find((w) => w.type === "beszel")).toEqual(expect.objectContaining({ version: 2, systemId: "sys" }));
|
expect(widgets.find((w) => w.type === "beszel")).toEqual(expect.objectContaining({ version: 2, systemId: "sys" }));
|
||||||
|
expect(widgets.find((w) => w.type === "pulse")).toEqual(expect.objectContaining({ version: 2 }));
|
||||||
expect(widgets.find((w) => w.type === "crowdsec")).toEqual(expect.objectContaining({ limit24h: true }));
|
expect(widgets.find((w) => w.type === "crowdsec")).toEqual(expect.objectContaining({ limit24h: true }));
|
||||||
expect(widgets.find((w) => w.type === "docker")).toEqual(
|
expect(widgets.find((w) => w.type === "docker")).toEqual(
|
||||||
expect.objectContaining({ server: "docker-local", container: "c1" }),
|
expect.objectContaining({ server: "docker-local", container: "c1" }),
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ function formatResourceCount(total, active) {
|
|||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: resourcesData, error: resourcesError } = useWidgetAPI(widget, "resources");
|
const version = widget.version ?? 1;
|
||||||
|
const { data: resourcesData, error: resourcesError } = useWidgetAPI(widget, version === 2 ? "summary" : "resources");
|
||||||
|
|
||||||
if (resourcesError) {
|
if (resourcesError) {
|
||||||
return <Container service={service} error={resourcesError} />;
|
return <Container service={service} error={resourcesError} />;
|
||||||
@@ -55,6 +56,17 @@ export default function Component({ service }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version === 2) {
|
||||||
|
// pulse v6 (v2 widget) returns the counts directly in the summary
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="pulse.nodes" value={resourcesData.nodes} />
|
||||||
|
<Block label="pulse.vms" value={resourcesData.vms} />
|
||||||
|
<Block label="pulse.lxcs" value={resourcesData.containers} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let resources = resourcesData.resources;
|
let resources = resourcesData.resources;
|
||||||
if (!resources && resourcesData.count === 0) {
|
if (!resources && resourcesData.count === 0) {
|
||||||
resources = [];
|
resources = [];
|
||||||
|
|||||||
@@ -27,6 +27,27 @@ describe("widgets/pulse/component", () => {
|
|||||||
expect(screen.getByText("pulse.nodes")).toBeInTheDocument();
|
expect(screen.getByText("pulse.nodes")).toBeInTheDocument();
|
||||||
expect(screen.getByText("pulse.vms")).toBeInTheDocument();
|
expect(screen.getByText("pulse.vms")).toBeInTheDocument();
|
||||||
expect(screen.getByText("pulse.lxcs")).toBeInTheDocument();
|
expect(screen.getByText("pulse.lxcs")).toBeInTheDocument();
|
||||||
|
expect(useWidgetAPI).toHaveBeenCalledWith({ type: "pulse" }, "resources");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders Pulse v6 summary counts", () => {
|
||||||
|
useWidgetAPI.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
nodes: 2,
|
||||||
|
vms: 8,
|
||||||
|
containers: 12,
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { container } = renderWithProviders(<Component service={{ widget: { type: "pulse", version: 2 } }} />, {
|
||||||
|
settings: { hideErrors: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(useWidgetAPI).toHaveBeenCalledWith({ type: "pulse", version: 2 }, "summary");
|
||||||
|
expectBlockValue(container, "pulse.nodes", 2);
|
||||||
|
expectBlockValue(container, "pulse.vms", 8);
|
||||||
|
expectBlockValue(container, "pulse.lxcs", 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders error UI when the resources endpoint errors", () => {
|
it("renders error UI when the resources endpoint errors", () => {
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ const widget = {
|
|||||||
resources: {
|
resources: {
|
||||||
endpoint: "api/resources",
|
endpoint: "api/resources",
|
||||||
},
|
},
|
||||||
|
summary: {
|
||||||
|
endpoint: "api/state/summary",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { describe, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { expectWidgetConfigShape } from "test-utils/widget-config";
|
import { expectWidgetConfigShape } from "test-utils/widget-config";
|
||||||
|
|
||||||
@@ -8,4 +8,8 @@ describe("pulse widget config", () => {
|
|||||||
it("exports a valid widget config", () => {
|
it("exports a valid widget config", () => {
|
||||||
expectWidgetConfigShape(widget);
|
expectWidgetConfigShape(widget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("maps the Pulse v6 summary endpoint", () => {
|
||||||
|
expect(widget.mappings.summary.endpoint).toBe("api/state/summary");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user