Merge branch 'rework/docker' into main
This commit is contained in:
commit
1fc118ef87
9 changed files with 104 additions and 302 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,3 +17,4 @@ yarn-error.log*
|
|||
/build/
|
||||
/data/
|
||||
/confs/
|
||||
/private/
|
|
@ -48,24 +48,6 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||
defer src='https://static.cloudflareinsights.com/beacon.min.js'
|
||||
data-cf-beacon='{"token": "826fc083aa86417890c0ceb3e0a597fa"}'>
|
||||
</Script>
|
||||
<Script id="matomo_analytics">
|
||||
{`
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
|
||||
_paq.push(["setCookieDomain", "www.neshweb.net"]);
|
||||
_paq.push(["disableCookies"]);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="//tracking.neshweb.net/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '2']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
`}
|
||||
</Script>
|
||||
|
||||
<PageNavbar mobile={isMobile}/>
|
||||
<Main>
|
||||
|
|
|
@ -32,6 +32,7 @@ export enum Status {
|
|||
|
||||
export enum ServiceLocation {
|
||||
brr7_4800u = "brr7-4800u",
|
||||
tower_0 = "tower-0",
|
||||
other = ""
|
||||
}
|
||||
|
||||
|
|
11
interfaces/DockerStatus.ts
Normal file
11
interfaces/DockerStatus.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { ServiceLocation } from './CardTypes';
|
||||
export interface DockerInfo {
|
||||
name: string,
|
||||
status: DockerStatus,
|
||||
id: string
|
||||
location: ServiceLocation,
|
||||
}
|
||||
|
||||
export enum DockerStatus {
|
||||
running = "running",
|
||||
}
|
|
@ -1,13 +1,29 @@
|
|||
import Docker from 'dockerode'
|
||||
import ApiSecret from '../../private/portainer_api_secret.json'
|
||||
import { DockerInfo } from '../../interfaces/DockerStatus';
|
||||
import { ServiceLocation } from '../../interfaces/CardTypes';
|
||||
|
||||
export default async function ContainersAPI(req: any, res: any) {
|
||||
const token = JSON.parse(JSON.stringify(ApiSecret.token));
|
||||
|
||||
try {
|
||||
const options = {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
path: '/v1.41/containers/json'
|
||||
};
|
||||
var docker = new Docker({ socketPath: options.socketPath });
|
||||
const list = await docker.listContainers({ all: true })
|
||||
const res1 = await fetch('https://portainer.neshweb.net/api/endpoints/2/docker/containers/json', {
|
||||
method: "GET",
|
||||
headers: {"X-API-Key": token}
|
||||
});
|
||||
|
||||
const unparsed = await res1.json();
|
||||
let list: DockerInfo[] = [];
|
||||
|
||||
unparsed.forEach((entry: any) => {
|
||||
let newEntry = {} as DockerInfo;
|
||||
|
||||
newEntry.name = entry.Names[0].substring(1);
|
||||
newEntry.status = entry.State;
|
||||
newEntry.id = entry.Id;
|
||||
newEntry.location = ServiceLocation.tower_0;
|
||||
list.push(newEntry);
|
||||
});
|
||||
|
||||
res.status(200).json(list);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Head from 'next/head'
|
||||
import { Game } from '../interfaces/CardTypes';
|
||||
import { PageContentBox, PageDescription, PageTitle, CardContentGame } from '../components/styles/content'
|
||||
import GameList from '../public/pages.json';
|
||||
import GameList from '../public/data/pages.json';
|
||||
|
||||
function Servers() {
|
||||
// TODO: unuggly this shit
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ReactElement } from 'react'
|
|||
import useSWR from 'swr';
|
||||
import { CardContentService, PageContentBox, PageDescription, PageTitle } from '../components/styles/content';
|
||||
import ServiceList from '../public/data/pages.json';
|
||||
import { DockerInfo } from '../interfaces/DockerStatus';
|
||||
|
||||
const fetcher = (url: string) => fetch(url).then((res) => res.json())
|
||||
|
||||
|
@ -56,82 +57,12 @@ function Services() {
|
|||
)
|
||||
}
|
||||
|
||||
async function getStatus(entry: Service, containers: Dockerode.ContainerInfo[]) {
|
||||
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
|
||||
|
||||
// Location BRR7-4800U
|
||||
if (entry.location === ServiceLocation.brr7_4800u) {
|
||||
// Type APP
|
||||
if (entry.type === ServiceType.app) {
|
||||
await fetch(entry.href)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
switch (response.status) {
|
||||
case 200:
|
||||
case 301:
|
||||
case 302:
|
||||
entry.status = Status.online;
|
||||
break;
|
||||
default:
|
||||
entry.status = Status.offline;
|
||||
}
|
||||
}
|
||||
else {
|
||||
entry.status = Status.offline;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error pinging Website: ", error);
|
||||
entry.status = Status.error;
|
||||
})
|
||||
}
|
||||
// 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 (containers[i].Names.includes("/" + entry.docker_container_name)) {
|
||||
// so far only "running" is properly implemented, mroe cases to follow as needed
|
||||
switch (container.State) {
|
||||
case "running":
|
||||
entry.status = Status.online;
|
||||
break;
|
||||
default:
|
||||
console.log("Container Status " + container.State + " 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 {
|
||||
console.warn("Service Type for Service " + entry.name + " not specified or invalid");
|
||||
entry.status = Status.error;
|
||||
}
|
||||
}
|
||||
// Location Other
|
||||
// TODO: implement docker type for other locations
|
||||
else if (entry.location === ServiceLocation.other) {
|
||||
// Currently uses the same handling as app type for the other location
|
||||
// Type APP
|
||||
if (entry.type === ServiceType.app) {
|
||||
await fetch(entry.href)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
|
@ -154,15 +85,54 @@ async function getStatus(entry: Service, containers: Dockerode.ContainerInfo[])
|
|||
entry.status = Status.error;
|
||||
})
|
||||
}
|
||||
// If no Location matches
|
||||
// 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 {
|
||||
console.warn("Service Location for Service " + entry.name + " not specified");
|
||||
console.warn("Service Type for Service " + entry.name + " not specified or invalid");
|
||||
entry.status = Status.error;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
const fetchFullDataArray = (containerData: Dockerode.ContainerInfo[], dataSet: Service[]) => {
|
||||
const fetchFullDataArray = (containerData: DockerInfo[], dataSet: Service[]) => {
|
||||
const fetchStatus = (entry: Service) => getStatus(entry, containerData);
|
||||
return Promise.all(dataSet.map(fetchStatus));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"warn": "Note: Registration requires approval",
|
||||
"type": "docker",
|
||||
"docker_container_name": "nextcloud",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Kavita",
|
||||
|
@ -18,17 +18,7 @@
|
|||
"warn": "Registration via Admin invite",
|
||||
"type": "docker",
|
||||
"docker_container_name": "kavita",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Komga",
|
||||
"icon": "/icons/komga-logo.png",
|
||||
"href": "https://komga.neshweb.net",
|
||||
"desc": "Self-hosted Comic Library",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "komga",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Calibre Web",
|
||||
|
@ -36,8 +26,9 @@
|
|||
"href": "https://calibre.neshweb.net/",
|
||||
"desc": "Self-hosted Ebook Library Service",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "app",
|
||||
"location": "brr7-4800u"
|
||||
"type": "docker",
|
||||
"docker_container_name": "calibre-web",
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "PeerTube",
|
||||
|
@ -47,7 +38,7 @@
|
|||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "peertube",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Mastodon",
|
||||
|
@ -57,7 +48,7 @@
|
|||
"warn": "Note: Registration requires approval",
|
||||
"type": "docker",
|
||||
"docker_container_name": "mastodon-web",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -68,7 +59,7 @@
|
|||
"warn": "Note: Invite only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "vaultwarden",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "File Browser",
|
||||
|
@ -77,7 +68,7 @@
|
|||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "filebrowser",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Jellyfin",
|
||||
|
@ -87,7 +78,7 @@
|
|||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "jellyfin",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Navidrome",
|
||||
|
@ -97,7 +88,7 @@
|
|||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "navidrome",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Picard",
|
||||
|
@ -106,7 +97,7 @@
|
|||
"warn": "Note: Access only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "picard",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Gitlab",
|
||||
|
@ -116,7 +107,7 @@
|
|||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "gitlab",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Portainer",
|
||||
|
@ -126,7 +117,7 @@
|
|||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "portainer",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Nginx Proxy Manager",
|
||||
|
@ -136,26 +127,16 @@
|
|||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "nginx-prox",
|
||||
"location": "brr7-4800u"
|
||||
"location": "tower-0"
|
||||
},
|
||||
{
|
||||
"name": "Grafana",
|
||||
"icon": "/icons/grafana-logo.svg",
|
||||
"href": "https://monitoring.neshweb.net/",
|
||||
"desc": "Server Monitoring Utility",
|
||||
"name": "Proxmox",
|
||||
"icon": "/icons/proxmox-logo.png",
|
||||
"href": "https://proxmox.neshweb.net/",
|
||||
"desc": "Hypervisor Webinterface",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "grafana",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Matomo",
|
||||
"href": "https://tracking.neshweb.net/",
|
||||
"desc": "Traffic Tracking Utility",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "matomo-web",
|
||||
"location": "brr7-4800u"
|
||||
"type": "app",
|
||||
"location": ""
|
||||
}
|
||||
],
|
||||
"games": {
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
{
|
||||
"services": [
|
||||
{
|
||||
"name": "Nextcloud",
|
||||
"icon": "/icons/nextcloud-logo.svg",
|
||||
"href": "https://nextcloud.neshweb.net/",
|
||||
"desc": "Self-hosted Cloud Storage Service",
|
||||
"warn": "Note: Registration requires approval",
|
||||
"type": "docker",
|
||||
"docker_container_name": "nextcloud",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Komga",
|
||||
"icon": "/icons/komga-logo.png",
|
||||
"href": "https://komga.neshweb.net/",
|
||||
"desc": "Self-hosted Comic Library",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "komga",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Calibre Web",
|
||||
"icon": "/icons/calibre-logo.ico",
|
||||
"href": "https://calibre.neshweb.net/",
|
||||
"desc": "Self-hosted Ebook Library Service",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "app",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "PeerTube",
|
||||
"icon": "/icons/peertube-logo.svg",
|
||||
"href": "https://tube.neshweb.net/",
|
||||
"desc": "Self-hosted PeerTube Instance",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "peertube",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Mastodon",
|
||||
"icon": "/icons/mastodon-logo.svg",
|
||||
"href": "https://mastodon.neshweb.net/",
|
||||
"desc": "Self-hosted Mastodon Instance",
|
||||
"warn": "Note: Registration requires approval",
|
||||
"type": "docker",
|
||||
"docker_container_name": "mastodon-web",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "File Browser",
|
||||
"href": "https://files.neshweb.net/",
|
||||
"desc": "Server File Browser",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "filebrowser",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Jellyfin",
|
||||
"icon": "/icons/jellyfin-logo.svg",
|
||||
"href": "https://jellyfin.neshweb.net/",
|
||||
"desc": "Open-Source, Self-Hosted Media Platform",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "jellyfin",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Navidrome",
|
||||
"icon": "/icons/navidrome-logo.png",
|
||||
"href": "https://navidrome.neshweb.net/",
|
||||
"desc": "Open-Source, Self-Hosted Music Streaming Platform",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "navidrome",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Picard",
|
||||
"href": "https://picard.neshweb.net/",
|
||||
"desc": "MP3 Tagger",
|
||||
"warn": "Note: Access only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "picard",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Gitlab",
|
||||
"icon": "/icons/gitlab-logo.svg",
|
||||
"href": "https://gitlab.neshweb.net/",
|
||||
"desc": "Self-hosted Git Service",
|
||||
"warn": "Note: Registration only via Admin",
|
||||
"type": "docker",
|
||||
"docker_container_name": "gitlab",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Portainer",
|
||||
"icon": "/icons/portainer-logo.png",
|
||||
"href": "https://portainer.neshweb.net/",
|
||||
"desc": "Docker Container Manager",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "portainer",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Nginx Proxy Manager",
|
||||
"icon": "/icons/npm-logo.png",
|
||||
"href": "https://nginx.neshweb.net/",
|
||||
"desc": "Web-based Nginx Proxy Manager",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "nginx-prox",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Grafana",
|
||||
"icon": "/icons/grafana-logo.svg",
|
||||
"href": "https://monitoring.neshweb.net/",
|
||||
"desc": "Server Monitoring Utility",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "grafana",
|
||||
"location": "brr7-4800u"
|
||||
},
|
||||
{
|
||||
"name": "Matomo",
|
||||
"href": "https://tracking.neshweb.net/",
|
||||
"desc": "Traffic Tracking Utility",
|
||||
"warn": "Note: Admin Only",
|
||||
"type": "docker",
|
||||
"docker_container_name": "matomo-web",
|
||||
"location": "brr7-4800u"
|
||||
}
|
||||
],
|
||||
"games": {
|
||||
"minecraft": {
|
||||
"name": "Minecraft",
|
||||
"icon": "/icons/minecraft-logo.png",
|
||||
"href": "https://minecraft.neshweb.net/",
|
||||
"desc": "View all currently available Minecraft Servers and their mods"
|
||||
},
|
||||
"ready_or_not": {
|
||||
"name": "Ready or Not",
|
||||
"icon": "/icons/ron-logo.png",
|
||||
"href": "https://readyornot.neshweb.net/",
|
||||
"desc": "Collection of Floor Plans for the Game 'Ready or Not'"
|
||||
},
|
||||
"zomboid": {
|
||||
"name": "Zomboid",
|
||||
"icon": "/icons/zomboid-logo.png",
|
||||
"ip": "91.13.248.30",
|
||||
"status": "Online"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue