from app.utils import registerQuery, registerMutation, createType, registerSubscription from . import docker_client, KeyValue, formatTime from docker.errors import APIError, ImageNotFound import docker from typing import NamedTuple import aiohttp from dataclasses import dataclass from uuid import uuid4 import asyncio import re from app.exception import PMException DockerImage = createType("DockerImage") # A tag name must be valid ASCII and may contain lowercase and uppercase letters, digits, underscores, periods and dashes. # A tag name may not start with a period or a dash and may contain a maximum of 128 characters. TAG_REG = re.compile(r"^[a-z0-9_][a-z0-9_\.\-]{0,127}$", re.IGNORECASE) @dataclass class HistoryEntry: operation: str argument: str comment: str tags: list[str] date: int size: int @registerQuery("dockerImages") def resolve_images(*_, onlyFinal):
from dataclasses import dataclass from datetime import datetime from app.api import logdb from app.utils import createType, registerQuery DockerLog = createType("DockerLog") @dataclass class DockerLogEntry: rowid: int date: str image: str container: str stream: str log: str @classmethod def from_row(cls, row): rowid = row[0] date = str(datetime.fromtimestamp(row[1])) return cls(rowid, date, *row[2:]) def query_from(image_filter, container_filter, offset, size): cur = logdb.cursor() total = next(cur.execute("SELECT count(rowid) FROM docker_logs"))[0] filters = ["TRUE"] args = []
import shlex from . import kv_to_dict from app.api import create_shell from app.utils import createType, registerMutation, registerQuery from starlette.websockets import WebSocketDisconnect from app.exception import PMException DockerContainerShell = createType("DockerContainerShell") shells = {} @registerQuery("dockerContainerShells") def resolve_docker_shells(*_): return shells.values() @registerQuery("dockerContainerShellById") def resolve_docker_shells(id, *_): return shells.get(id) @registerMutation("deleteDockerContainerShell") def delete_shell(*_, id): if id not in shells: raise PMException("Invalid id") if shells[id].running: raise PMException("The shell is still running") shells.pop(id)
@TraefikRouter.field("entryPoints") async def resolve_traefik_enabled(router, *_): if "entryPoints" not in router: return [] entrypoints = { e["name"]: e for e in await traefik_http().get_entrypoints() } results = [] for name in router["entryPoints"]: results.append(entrypoints[name]) return results TraefikHTTPRouter = createType("TraefikHTTPRouter") @TraefikHTTPRouter.field("priority") def resolve_traefikrouter_name(router, *_): if "priority" in router: return router["priority"] if "rule" in router: return len(router["rule"]) return 0 @TraefikHTTPRouter.field("middlewares") async def middlewares(router, *_): if "middlewares" not in router: return []
from app.utils import registerQuery, registerMutation, createType from . import docker_client, KeyValue, formatTime, kv_to_dict from docker.errors import APIError, NotFound from docker.types import IPAMConfig, IPAMPool from app.exception import PMException DockerNetwork = createType("DockerNetwork") DockerNetworkConnection = createType("DockerNetworkConnection") @registerQuery("dockerNetworks") def resolve_networks(*_): return docker_client.networks.list(greedy=True) @DockerNetwork.field("labels") def resolve_network_labels(network, _): for label in network.attrs["Labels"].items(): yield KeyValue(*label) @DockerNetwork.field("created") def resolve_network_created(network, _): return formatTime(network.attrs["Created"]) @DockerNetwork.field("driver") def resolve_network_driver(network, _): return network.attrs["Driver"]
async def resolve_usedBy(service, *_): if "usedBy" not in service: return [] return await traefik_http().get_routers_used_by(service["usedBy"]) @TraefikService.field("type") async def resolve_type(service, *_): type = service.get("type", "internal") if type == "loadbalancer": return "loadBalancer" return type TraefikServiceLoadBalancerHealthCheck = createType( "TraefikServiceLoadBalancerHealthCheck" ) TraefikServiceLoadBalancerHealthCheck.field("headers")(create_kv_resolver("headers")) TraefikWeighted = createType("TraefikWeighted") @TraefikWeighted.field("services") def resolve_weighted_services(weighted, *_): services = weighted.get("services", []) return services
from functools import wraps import time from app.utils import registerQuery, registerMutation, createType, create_node_id from app.api import get_powerdns_http_api as dns_http @registerQuery("dnsZones") async def get_dns_zones(*_): return await dns_http().get_zones() DnsZone = createType("DnsZone") @DnsZone.field("nodeId") def resolve_nodeid(zone, *_): return create_node_id("DNS_ZONE", zone["id"]) @DnsZone.field("name") def resolve_name(zone, *_): return zone["name"] @DnsZone.field("soa") async def resolve_soa(zone, *_): return await dns_http().get_soa(zone["id"]) @DnsZone.field("rules") async def resolve_rules(zone, *_):
import re import shlex from typing import NamedTuple from dataclasses import dataclass from app.utils import createType, registerMutation, registerQuery from docker.errors import APIError, NotFound from docker.types import Mount from . import KeyValue, docker_client, formatTime, kv_to_dict from .image import resolve_image_name from app.exception import PMException DockerContainer = createType("DockerContainer") DockerContainerMount = createType("DockerContainerMount") DockerContainerConnection = createType("DockerContainerConnection") class ContainerMount(NamedTuple): type: str source: str = None target: str = None readonly: bool = False volume: str = None name: str = None @registerQuery("dockerContainers") def resolve_containers(*_, onlyRunning): return docker_client.containers.list(all=not onlyRunning)
from app.utils import createType, registerQuery, create_node_id from app.api import get_traefik_http_api as traefik_http TraefikEntrypoint = createType("TraefikEntrypoint") @registerQuery("traefikEntrypoints") async def resolve_TraefikEntrypoints(*_, protocols=[]): return await traefik_http().get_entrypoints() @TraefikEntrypoint.field("nodeId") async def resolve_nodeid(entrypoint, *_): return create_node_id("TRAEFIK_EP", entrypoint["name"]) @TraefikEntrypoint.field("usedBy") async def resolved_usedby(entrypoint, *_): if entrypoint["protocol"] == "udp": protocols = ["udp"] else: protocols = ["http", "tcp"] routers = await traefik_http().get_routers(protocols) return [ router for router in routers if entrypoint["name"] in router["entryPoints"] ]
"TraefikMiddlewareHeaders": "headers", "TraefikMiddlewareIpWhiteList": "ipWhiteList", "TraefikMiddlewareInFlightReq": "inFlightReq", "TraefikMiddlewarePassTLSClientCert": "passTLSClientCert", "TraefikMiddlewareRateLimit": "rateLimit", "TraefikMiddlewareRedirectRegex": "redirectRegex", "TraefikMiddlewareRedirectScheme": "redirectScheme", "TraefikMiddlewareReplacePath": "replacePath", "TraefikMiddlewareReplacePathRegex": "replacePathRegex", "TraefikMiddlewareRetry": "retry", "TraefikMiddlewareStripPrefix": "stripPrefix", "TraefikMiddlewareStripPrefixRegex": "stripPrefixRegex", } for graphql_name, type_name in middlewares.items(): MiddlewareType = createType(graphql_name) MiddlewareType.field("type")(create_type_resolver(type_name)) create_mutation_resolver(graphql_name, type_name) TraefikMiddlewareHeadersInfo = createType("TraefikMiddlewareHeadersInfo") TraefikMiddlewareHeadersInfo.field("customRequestHeaders")( create_kv_resolver("customRequestHeaders")) TraefikMiddlewareHeadersInfo.field("customResponseHeaders")( create_kv_resolver("customResponseHeaders")) TraefikMiddlewareHeadersInfo.field("sslProxyHeaders")( create_kv_resolver("sslProxyHeaders")) TraefikMiddlewareRetryInfo = createType("TraefikMiddlewareRetryInfo")
from app.utils import registerQuery, registerMutation, createType from . import docker_client, KeyValue, formatTime from docker.errors import APIError from app.exception import PMException DockerVolume = createType("DockerVolume") @registerQuery("dockerVolumes") def resolve_volumes(*_): return docker_client.volumes.list() @DockerVolume.field("labels") def resolve_volume_labels(volume, _): return [ KeyValue(*label) for label in (volume.attrs["Labels"] or {}).items() ] @DockerVolume.field("created") def resolve_volume_created(volume, _): return formatTime(volume.attrs["CreatedAt"]) @DockerVolume.field("mountpoint") def resolve_volume_mountpoint(volume, _): return volume.attrs["Mountpoint"] @DockerVolume.field("usedBy")
lua = lua[20:-4] lua = lua.replace("\\x5c", "\\") lua = lua.replace("\\x22", '"') lua = lua.replace("\\x27", "'") lua = lua.replace("\\x0a", "\n") return lua def parse_lua_record(record): type, _, content = record.partition(" ") unescaped_content = unescape_lua(content[1:-1]) return type, unescaped_content DnsRule = createType("DnsRule") @registerQuery("dnsRules") async def get_dns_rules(*_): return await dns_http().get_rules() @DnsRule.field("name") def resolve_name(rule, *_): return rule["name"] @DnsRule.field("isLua") def resolve_islua(rule, *_): return rule["type"] == "LUA"
from dataclasses import dataclass from datetime import datetime from app.api import logdb from app.utils import createType, registerQuery TraefikLog = createType("TraefikLog") @dataclass class TraefikLogEntry: rowid: int date: int origin: str status: int host: str method: str path: str port: int protocol: str scheme: str routerName: str entrypointName: str serviceName: str @classmethod def from_row(cls, row): rowid = row[0] date = str(datetime.fromtimestamp(row[1])) return cls(rowid, date, *row[2:])