main-site/pages/services.tsx

158 lines
4.7 KiB
TypeScript
Raw Normal View History

2022-12-03 20:02:13 +00:00
import Head from 'next/head'
2022-12-17 00:20:58 +00:00
import { Service, Status, ServiceType, ServiceLocation } from '../interfaces/CardTypes';
2022-12-03 20:02:13 +00:00
import Dockerode from 'dockerode';
import { ReactElement } from 'react'
import useSWR from 'swr';
import { CardContentService, PageContentBox, PageDescription, PageTitle } from '../components/styles/content';
2023-01-18 10:39:39 +00:00
import ServiceList from '../public/data/pages.json';
import { DockerInfo } from '../interfaces/DockerStatus';
2022-12-03 20:02:13 +00:00
const fetcher = (url: string) => fetch(url).then((res) => res.json())
2022-12-03 20:02:13 +00:00
function Services() {
const { initialData, fullData, loadingFull, error } = useServices();
let content: ReactElement = <></>;
if (error) { content = <div>Error loading data</div> }
else if (loadingFull) {
content =
<PageContentBox>
{initialData?.map((item: Service) => (
2022-12-17 00:20:58 +00:00
<CardContentService key={item.name} content={item} />
))}
</PageContentBox>
}
else if (fullData) {
content =
<PageContentBox>
{fullData.map((item: Service) => (
2022-12-17 00:20:58 +00:00
<CardContentService key={item.name} content={item} />
))}
</PageContentBox>
}
else {
content = <div>Error loading data</div>
}
2022-12-03 20:02:13 +00:00
return (
<>
<Head>
2022-12-18 03:56:35 +00:00
<title>Neshweb - Services</title>
2022-12-03 20:02:13 +00:00
<meta charSet='utf-8' />
<link rel="icon" href="/favicon.ico" />
<meta name="description" content="Lists all available Services, most likely up-to-date" />
2022-12-03 20:02:13 +00:00
</Head>
<PageTitle>
2022-12-03 20:02:13 +00:00
Service List
</PageTitle>
2022-12-03 20:02:13 +00:00
<PageDescription>
2022-12-03 20:02:13 +00:00
Lists all available Services, most likely up-to-date
</PageDescription>
{content}
2022-12-03 20:02:13 +00:00
</>
)
}
async function getStatus(entry: Service, containers: DockerInfo[]) {
// Currently the only location supporting different fetching depending on type is brr7-4800u
// Others to follow but low prio as this is currently the only location used
2023-03-14 21:32:53 +00:00
// Type APP
if (entry.type === ServiceType.app) {
await fetch(entry.href)
2022-12-11 16:11:02 +00:00
.then((response) => {
if (response.ok) {
switch (response.status) {
case 200:
case 301:
case 302:
2022-12-17 00:20:58 +00:00
entry.status = Status.online;
2022-12-11 16:11:02 +00:00
break;
default:
2022-12-17 00:20:58 +00:00
entry.status = Status.offline;
}
2022-12-11 16:11:02 +00:00
}
else {
2022-12-17 00:20:58 +00:00
entry.status = Status.offline;
2022-12-11 16:11:02 +00:00
}
})
.catch((error) => {
console.error("Error pinging Website: ", error);
2022-12-17 00:20:58 +00:00
entry.status = Status.error;
2022-12-11 16:11:02 +00:00
})
}
2023-03-14 21:32:53 +00:00
// Type Docker
else if (entry.type === ServiceType.docker) {
if (entry.name !== null) {
let found = false;
for (let i = 0; i < containers.length; i++) {
const container = containers[i];
// Docker API returns container names with / prepended
if (container.name === entry.docker_container_name) {
if (container.location === entry.location) {
// so far only "running" is properly implemented, mroe cases to follow as needed
switch (container.status) {
case "running":
entry.status = Status.online;
break;
default:
console.log("Container Status " + container.status + " has no case implemented");
entry.status = Status.offline;
}
found = true;
// cancel the for
break;
}
}
// If container name is not missing the container is set to offline
else {
entry.status = Status.offline;
}
}
if (!found) {
console.warn("Container for " + entry.name + " could not be found");
}
}
// if name is null do not enter for loop
else {
console.error("Container Name not specified");
entry.status = Status.error;
}
}
// If no Type matches
else {
2023-03-14 21:32:53 +00:00
console.warn("Service Type for Service " + entry.name + " not specified or invalid");
2022-12-17 00:20:58 +00:00
entry.status = Status.error;
2022-12-03 20:02:13 +00:00
}
return entry;
}
const fetchFullDataArray = (containerData: DockerInfo[], dataSet: Service[]) => {
const fetchStatus = (entry: Service) => getStatus(entry, containerData);
return Promise.all(dataSet.map(fetchStatus));
}
function useServices() {
const { data: containerData, error: containerError } = useSWR('/api/containers', fetcher);
// TODO: unfuck this
const initialData: Service[] = JSON.parse(JSON.stringify(ServiceList.services));
initialData.forEach((service) => {
if (service.status === undefined) service.status = Status.loading;
})
const { data: fullData, error: fullError } = useSWR((containerData) ? [containerData, initialData] : null, fetchFullDataArray)
const loadingFull = !fullData && !fullError
return {
initialData,
fullData,
loadingFull,
error: fullError || containerError,
};
2022-12-03 20:02:13 +00:00
}
2023-01-18 10:32:28 +00:00
export default Services