mirror of
https://github.com/KevinMidboe/infra-map.git
synced 2026-01-13 04:36:33 +00:00
source, static files & Dockerfile
This commit is contained in:
92
src/lib/server/filament.ts
Normal file
92
src/lib/server/filament.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import type { Filament } from '$lib/interfaces/printer';
|
||||
|
||||
const filament: Filament[] = [
|
||||
{
|
||||
Hex: '#DD4344',
|
||||
Color: 'Scarlet Red',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 2,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742848731'
|
||||
},
|
||||
{
|
||||
Hex: '#61C57F',
|
||||
Color: 'Grass Green',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 2,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742783195'
|
||||
},
|
||||
{
|
||||
Hex: '#F7DA5A',
|
||||
Color: 'Lemon Yellow',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 2,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742717659'
|
||||
},
|
||||
{
|
||||
Hex: '#E8DBB7',
|
||||
Color: 'Desert Tan',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 1,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=48612736401756'
|
||||
},
|
||||
{
|
||||
Hex: "url('https://www.transparenttextures.com/patterns/asfalt-dark.png'",
|
||||
Color: 'White Marble',
|
||||
Material: 'PLA Marble',
|
||||
Weight: '1kg',
|
||||
Count: 1,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/products/pla-marble?variant=43964050964699'
|
||||
},
|
||||
{
|
||||
Hex: '#0078C0',
|
||||
Color: 'Marine Blue',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 1,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996751073499'
|
||||
},
|
||||
{
|
||||
Hex: '#000000',
|
||||
Color: 'Charcoal',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 2,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742750427'
|
||||
},
|
||||
{
|
||||
Hex: '#ffffff',
|
||||
Color: 'Ivory White',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 2,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742586587'
|
||||
},
|
||||
{
|
||||
Hex: '#E8AFCE',
|
||||
Color: 'Sakura Pink',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 1,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742684891'
|
||||
},
|
||||
{
|
||||
Hex: '#AE96D5',
|
||||
Color: 'Lilac Purple',
|
||||
Material: 'PLA Matte',
|
||||
Weight: '1kg',
|
||||
Count: 1,
|
||||
Link: 'https://eu.store.bambulab.com/en-no/collections/pla/products/pla-matte?variant=42996742914267'
|
||||
}
|
||||
];
|
||||
|
||||
export function filamentByColor(name: string) {
|
||||
return filament.find((f) => f.Color?.toLowerCase() === name?.toLowerCase());
|
||||
}
|
||||
|
||||
export function currentFilament(): Filament[] {
|
||||
return filament;
|
||||
}
|
||||
36
src/lib/server/homeassistant.ts
Normal file
36
src/lib/server/homeassistant.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import type { Entity } from '$lib/interfaces/homeassistant';
|
||||
|
||||
function buildHomeassistantRequest() {
|
||||
const url = env.HOMEASSISTANT_URL || '';
|
||||
const token = env.HOMEASSISTANT_TOKEN || '';
|
||||
|
||||
const options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
return { url, options };
|
||||
}
|
||||
|
||||
async function fetchHassStates() {
|
||||
const { url, options } = buildHomeassistantRequest();
|
||||
return fetch(url, options).then((resp) => resp.json());
|
||||
}
|
||||
|
||||
export async function fetchP1P(): Promise<Entity[]> {
|
||||
try {
|
||||
let hassStates = await fetchHassStates();
|
||||
|
||||
hassStates = hassStates.filter(
|
||||
(el: Entity) => el.attributes.friendly_name?.includes('P1P') === true
|
||||
);
|
||||
return hassStates;
|
||||
} catch (error) {
|
||||
console.log('ERROR! from fetchP1P:', error);
|
||||
return Promise.reject(null);
|
||||
}
|
||||
}
|
||||
116
src/lib/server/kubernetes.ts
Normal file
116
src/lib/server/kubernetes.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import * as k8s from '@kubernetes/client-node';
|
||||
import stream from 'stream';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const context = {
|
||||
name: 'kazan-insecure',
|
||||
user: 'admin',
|
||||
cluster: 'kazan-insecure'
|
||||
};
|
||||
|
||||
const kc = new k8s.KubeConfig();
|
||||
kc.loadFromDefault({ contexts: [context] });
|
||||
|
||||
const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
|
||||
const appsV1Api = kc.makeApiClient(k8s.AppsV1Api);
|
||||
|
||||
const k8sLog = new k8s.Log(kc);
|
||||
|
||||
export async function getReplicas() {
|
||||
try {
|
||||
const allReplicas = await appsV1Api.listReplicaSetForAllNamespaces();
|
||||
return allReplicas.items;
|
||||
} catch (error) {
|
||||
console.log('error when getting replicas:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPods() {
|
||||
try {
|
||||
const allPods = await k8sApi.listPodForAllNamespaces();
|
||||
return allPods.items;
|
||||
} catch (error) {
|
||||
console.log('error when getting k8s resources:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPod(name: string, namespace: string) {
|
||||
try {
|
||||
return await k8sApi.readNamespacedPodTemplate({ name, namespace });
|
||||
} catch (error) {
|
||||
console.log(`error when getting pod:`, error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getDeployments() {
|
||||
try {
|
||||
const allDeploys = await appsV1Api.listDeploymentForAllNamespaces();
|
||||
return allDeploys.items;
|
||||
} catch (error) {
|
||||
console.log('error when getting deployments:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getDaemons() {
|
||||
try {
|
||||
const allDaemons = await appsV1Api.listDaemonSetForAllNamespaces();
|
||||
return allDaemons.items;
|
||||
} catch (error) {
|
||||
console.log('error when getting daemons:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getNodes() {
|
||||
try {
|
||||
const nodes = await k8sApi.listNode();
|
||||
return nodes.items;
|
||||
} catch (error) {
|
||||
console.log('error when getting k8s nodes:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function createLogStream(podName: string, namespace: string, containerName: string) {
|
||||
// const logEmitter = new EventTarget(); // use EventTarget or EventEmitter
|
||||
const logEmitter = writable();
|
||||
|
||||
const maxLines = 400;
|
||||
let liveStream: stream.PassThrough | null = null;
|
||||
let logAbortController;
|
||||
|
||||
async function start() {
|
||||
// Live logs
|
||||
liveStream = new stream.PassThrough();
|
||||
liveStream.on('data', (chunk) => {
|
||||
let chunks = chunk.toString().split('\n').filter(Boolean);
|
||||
|
||||
console.log('chynjks length:', chunks?.length);
|
||||
if (chunks?.length > maxLines) {
|
||||
chunks = chunks.slice(maxLines);
|
||||
}
|
||||
|
||||
chunks.forEach((line) => logEmitter.set(line));
|
||||
});
|
||||
|
||||
console.log('setting logAbortController, prev:', logAbortController);
|
||||
logAbortController = await k8sLog.log(namespace, podName, containerName, liveStream, {
|
||||
follow: true,
|
||||
timestamps: false,
|
||||
pretty: false,
|
||||
tailLines: maxLines
|
||||
});
|
||||
}
|
||||
|
||||
function stop() {
|
||||
console.log('ending livestream!!');
|
||||
logAbortController?.abort();
|
||||
liveStream?.end();
|
||||
}
|
||||
|
||||
return { start, stop, logEmitter };
|
||||
}
|
||||
86
src/lib/server/proxmox.ts
Normal file
86
src/lib/server/proxmox.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import type { Cluster, Node } from '$lib/interfaces/proxmox';
|
||||
|
||||
function buildProxmoxRequest() {
|
||||
const url = env.PROXMOX_URL || 'https://10.0.0.50:8006/api2/json/';
|
||||
const token = env.PROXMOX_TOKEN || 'REPLACE_WITH_PROXMOX_TOKEN';
|
||||
const options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: token,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
return { url, options };
|
||||
}
|
||||
|
||||
async function fetchNodeVMs(node: Node) {
|
||||
const r = buildProxmoxRequest();
|
||||
r.url += 'nodes/' + node?.name + '/qemu';
|
||||
|
||||
return fetch(r.url, r?.options)
|
||||
.then((resp) => resp.json())
|
||||
.then((response) => response.data);
|
||||
}
|
||||
|
||||
async function fetchNodeLXCs(node: Node) {
|
||||
const r = buildProxmoxRequest();
|
||||
r.url += 'nodes/' + node?.name + '/lxc';
|
||||
|
||||
return fetch(r.url, r?.options)
|
||||
.then((resp) => resp.json())
|
||||
.then((response) => response.data);
|
||||
}
|
||||
|
||||
async function fetchNodeInfo(node: Node) {
|
||||
const r = buildProxmoxRequest();
|
||||
r.url += 'nodes/' + node?.name + '/status';
|
||||
|
||||
return fetch(r.url, r?.options)
|
||||
.then((resp) => resp.json())
|
||||
.then((response) => response.data);
|
||||
}
|
||||
|
||||
async function getClusterInfo() {
|
||||
const r = buildProxmoxRequest();
|
||||
r.url += 'cluster/status';
|
||||
|
||||
return fetch(r.url, r?.options)
|
||||
.then((resp) => resp.json())
|
||||
.then((response) => {
|
||||
const { data } = response;
|
||||
const cluster = data.filter((d: Node | Cluster) => d?.type === 'cluster')[0];
|
||||
const nodes = data.filter((d: Node | Cluster) => d?.type === 'node');
|
||||
|
||||
return { cluster, nodes };
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchNodes(): Promise<{ nodes: Node[]; cluster: Cluster | null }> {
|
||||
try {
|
||||
const { nodes, cluster } = await getClusterInfo();
|
||||
|
||||
const infoP = Promise.all(nodes.map((node: Node) => fetchNodeInfo(node)));
|
||||
const vmsP = Promise.all(nodes.map((node: Node) => fetchNodeVMs(node)));
|
||||
const lxcsP = Promise.all(nodes.map((node: Node) => fetchNodeLXCs(node)));
|
||||
|
||||
const [info, vms, lxcs] = await Promise.all([infoP, vmsP, lxcsP]);
|
||||
|
||||
return {
|
||||
cluster,
|
||||
nodes: nodes.map((node: Node, i: number) => {
|
||||
return {
|
||||
...node,
|
||||
info: info[i],
|
||||
vms: vms[i],
|
||||
lxcs: lxcs[i]
|
||||
};
|
||||
})
|
||||
};
|
||||
} catch (error) {
|
||||
console.log('ERROR from fetchnodes:', error);
|
||||
|
||||
return { nodes: [], cluster: null };
|
||||
}
|
||||
}
|
||||
22
src/lib/server/traefik.ts
Normal file
22
src/lib/server/traefik.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
const TRAEFIK_HTTP_URL = '/api/http';
|
||||
|
||||
function buildTraefikRequest(path: string) {
|
||||
const baseURL = env.TRAEFIK_URL || 'http://localhost:9000';
|
||||
const url = `${baseURL}${TRAEFIK_HTTP_URL}/${path}`;
|
||||
const options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
return { url, options };
|
||||
}
|
||||
|
||||
export async function getRouters() {
|
||||
const { url, options } = buildTraefikRequest('routers');
|
||||
|
||||
return fetch(url, options).then((resp) => resp.json());
|
||||
}
|
||||
Reference in New Issue
Block a user