chore: Abstract machines and modules
All checks were successful
Check workflows / check_workflows (push) Successful in 21s
Run pre-commit on all files / check (push) Successful in 24s
Check meta / check_dns (pull_request) Successful in 19s
Check meta / check_meta (pull_request) Successful in 18s
Check workflows / check_workflows (pull_request) Successful in 19s
Build all the nodes / bridge01 (pull_request) Successful in 1m13s
Build all the nodes / geo01 (pull_request) Successful in 1m14s
Build all the nodes / compute01 (pull_request) Successful in 1m44s
Build all the nodes / geo02 (pull_request) Successful in 1m12s
Build all the nodes / rescue01 (pull_request) Successful in 1m30s
Build all the nodes / storage01 (pull_request) Successful in 1m29s
Build all the nodes / vault01 (pull_request) Successful in 1m26s
Build all the nodes / web02 (pull_request) Successful in 1m19s
Run pre-commit on all files / check (pull_request) Successful in 24s
Build all the nodes / web01 (pull_request) Successful in 1m56s
Build all the nodes / web03 (pull_request) Successful in 1m25s
All checks were successful
Check workflows / check_workflows (push) Successful in 21s
Run pre-commit on all files / check (push) Successful in 24s
Check meta / check_dns (pull_request) Successful in 19s
Check meta / check_meta (pull_request) Successful in 18s
Check workflows / check_workflows (pull_request) Successful in 19s
Build all the nodes / bridge01 (pull_request) Successful in 1m13s
Build all the nodes / geo01 (pull_request) Successful in 1m14s
Build all the nodes / compute01 (pull_request) Successful in 1m44s
Build all the nodes / geo02 (pull_request) Successful in 1m12s
Build all the nodes / rescue01 (pull_request) Successful in 1m30s
Build all the nodes / storage01 (pull_request) Successful in 1m29s
Build all the nodes / vault01 (pull_request) Successful in 1m26s
Build all the nodes / web02 (pull_request) Successful in 1m19s
Run pre-commit on all files / check (pull_request) Successful in 24s
Build all the nodes / web01 (pull_request) Successful in 1m56s
Build all the nodes / web03 (pull_request) Successful in 1m25s
This adds subdirectories for the different types of systems, for the modules and the machines
This commit is contained in:
parent
c3f4e7ade6
commit
ecbad0a638
264 changed files with 49 additions and 38 deletions
|
@ -1 +0,0 @@
|
|||
use nix
|
|
@ -1,75 +0,0 @@
|
|||
# Copyright :
|
||||
# - Ryan Lahfa <ryan.lahfa@dgnum.eu> 2024
|
||||
#
|
||||
# Ce logiciel est un programme informatique servant à déployer des
|
||||
# configurations de serveurs via NixOS.
|
||||
#
|
||||
# Ce logiciel est régi par la licence CeCILL soumise au droit français et
|
||||
# respectant les principes de diffusion des logiciels libres. Vous pouvez
|
||||
# utiliser, modifier et/ou redistribuer ce programme sous les conditions
|
||||
# de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
|
||||
# sur le site "http://www.cecill.info".
|
||||
#
|
||||
# En contrepartie de l'accessibilité au code source et des droits de copie,
|
||||
# de modification et de redistribution accordés par cette licence, il n'est
|
||||
# offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
|
||||
# seule une responsabilité restreinte pèse sur l'auteur du programme, le
|
||||
# titulaire des droits patrimoniaux et les concédants successifs.
|
||||
#
|
||||
# A cet égard l'attention de l'utilisateur est attirée sur les risques
|
||||
# associés au chargement, à l'utilisation, à la modification et/ou au
|
||||
# développement et à la reproduction du logiciel par l'utilisateur étant
|
||||
# donné sa spécificité de logiciel libre, qui peut le rendre complexe à
|
||||
# manipuler et qui le réserve donc à des développeurs et des professionnels
|
||||
# avertis possédant des connaissances informatiques approfondies. Les
|
||||
# utilisateurs sont donc invités à charger et tester l'adéquation du
|
||||
# logiciel à leurs besoins dans des conditions permettant d'assurer la
|
||||
# sécurité de leurs systèmes et ou de leurs données et, plus généralement,
|
||||
# à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
|
||||
#
|
||||
# Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
|
||||
# pris connaissance de la licence CeCILL, et que vous en avez accepté les
|
||||
# termes.
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.dgn-chatops;
|
||||
inherit (lib) mkEnableOption mkIf;
|
||||
python3 = pkgs.python311;
|
||||
python3Pkgs = python3.pkgs;
|
||||
ircrobots = python3Pkgs.callPackage ./ircrobots.nix { };
|
||||
tortoise-orm = python3Pkgs.callPackage ./tortoise-orm.nix { };
|
||||
ps = python3Pkgs.makePythonPath [
|
||||
ircrobots
|
||||
tortoise-orm
|
||||
python3Pkgs.aiohttp
|
||||
];
|
||||
in
|
||||
{
|
||||
options.dgn-chatops = {
|
||||
enable = mkEnableOption "the ChatOps layer";
|
||||
};
|
||||
|
||||
# Our ChatOps bot.
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.irc-takumi = {
|
||||
description = "DGNum IRC automation bot, Takumi";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
PYTHONPATH = ps;
|
||||
};
|
||||
serviceConfig = {
|
||||
RuntimeDirectory = "takumi";
|
||||
StateDirectory = "takumi";
|
||||
DynamicUser = true;
|
||||
ExecStart = "${lib.getExe python3} ${./takumi.py}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
fetchFromGitea,
|
||||
pythonOlder,
|
||||
anyio,
|
||||
asyncio-rlock,
|
||||
asyncio-throttle,
|
||||
ircstates,
|
||||
async-stagger,
|
||||
async-timeout,
|
||||
python,
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "ircrobots";
|
||||
version = "0.7.0";
|
||||
format = "setuptools";
|
||||
disabled = pythonOlder "3.7";
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.dgnum.eu";
|
||||
owner = "DGNum";
|
||||
repo = pname;
|
||||
# No tag yet :(.
|
||||
rev = "63aa84b40450bd534fc232eee10e8088028c9f6d";
|
||||
hash = "sha256-gXiPy6wjPEtc9v0cG0lb2QVXDlU5Q8ncxJO0lBm2RSE=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
# too specific pins https://github.com/jesopo/ircrobots/issues/3
|
||||
sed -iE 's/anyio.*/anyio/' requirements.txt
|
||||
'';
|
||||
|
||||
propagatedBuildInputs = [
|
||||
anyio
|
||||
asyncio-rlock
|
||||
asyncio-throttle
|
||||
ircstates
|
||||
async-stagger
|
||||
async-timeout
|
||||
];
|
||||
|
||||
checkPhase = ''
|
||||
${python.interpreter} -m unittest test
|
||||
'';
|
||||
|
||||
pythonImportsCheck = [ "ircrobots" ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Asynchronous bare-bones IRC bot framework for python3";
|
||||
license = licenses.mit;
|
||||
homepage = "https://github.com/jesopo/ircrobots";
|
||||
maintainers = with maintainers; [ hexa ];
|
||||
};
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
fetchFromGitHub,
|
||||
poetry-core,
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "pypika-tortoise";
|
||||
version = "0.1.6";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "tortoise";
|
||||
repo = "pypika-tortoise";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-xx5FUMHh6413fsvwrEA+Q0tBmJWy00h5O6YijvrJyCE=";
|
||||
};
|
||||
|
||||
build-system = [ poetry-core ];
|
||||
|
||||
pythonImportsCheck = [ "pypika" ];
|
||||
|
||||
meta = {
|
||||
description = "";
|
||||
homepage = "https://github.com/tortoise/pypika-tortoise";
|
||||
changelog = "https://github.com/tortoise/pypika-tortoise/blob/${src.rev}/CHANGELOG.md";
|
||||
license = lib.licenses.asl20;
|
||||
maintainers = with lib.maintainers; [ raitobezarius ];
|
||||
};
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "takumi"
|
||||
version = "1.1.0"
|
||||
authors = [
|
||||
{ name = "Ryan Lahfa", email = "ryan@dgnum.eu" },
|
||||
]
|
||||
description = "Fully automatic day-to-day operations at DGNum"
|
||||
requires-python = ">=3.11"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://git.dgnum.eu/DGNum/infrastructure"
|
||||
Issues = "https://git.dgnum.eu/DGNum/infrastructure/issues"
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
python3 ? pkgs.python3,
|
||||
}:
|
||||
let
|
||||
takumi = python3.pkgs.buildPythonPackage rec {
|
||||
pname = "takumi";
|
||||
version = "1.1.0";
|
||||
pyproject = true;
|
||||
|
||||
src = ./.;
|
||||
|
||||
build-system = [ python3.pkgs.hatchling ];
|
||||
|
||||
dependencies = [
|
||||
(python3.pkgs.callPackage ./ircrobots.nix { })
|
||||
(python3.pkgs.callPackage ./tortoise-orm.nix { })
|
||||
python3.pkgs.aiohttp
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/bin
|
||||
cp -v takumi.py $out/bin/takumi.py
|
||||
chmod +x $out/bin/takumi.py
|
||||
wrapProgram $out/bin/takumi.py --prefix PYTHONPATH : "$PYTHONPATH"
|
||||
'';
|
||||
};
|
||||
in
|
||||
pkgs.mkShell { packages = [ takumi ]; }
|
|
@ -1,121 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
|
||||
from irctokens.line import build, Line
|
||||
from ircrobots.bot import Bot as BaseBot
|
||||
from ircrobots.server import Server as BaseServer
|
||||
from ircrobots.params import ConnectionParams
|
||||
|
||||
import aiohttp
|
||||
|
||||
BRIDGE_NICKNAME = "hermes"
|
||||
|
||||
SERVERS = [
|
||||
("dgnum", "irc.dgnum.eu")
|
||||
]
|
||||
|
||||
TEAMS = {
|
||||
"fai": ("tomate", "elias", "JeMaGius", "Luj", "catvayor", "Raito"),
|
||||
"marketing": ("cst1", "elias"),
|
||||
"bureau": ("Raito", "JeMaGius", "Luj", "gdd")
|
||||
}
|
||||
|
||||
# times format is 0700-29092024
|
||||
TRIGGER = '!'
|
||||
async def create_meet(title: str, times: list[str], timezone: str = "UTC") -> str:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
payload = {
|
||||
'name': title,
|
||||
'times': times,
|
||||
'timezone': timezone
|
||||
}
|
||||
async with session.post('https://api.meet.dgnum.eu/event', json=payload) as response:
|
||||
response.raise_for_status()
|
||||
id = (await response.json()).get('id')
|
||||
if not id:
|
||||
raise RuntimeError('No ID attributed to a meet')
|
||||
return f'https://meet.dgnum.eu/{id}'
|
||||
|
||||
def expand_times(times: list[str]) -> list[str]:
|
||||
expanded = []
|
||||
# TODO: verify the date exist in the calendar
|
||||
# TODO: verify that we don't write any duplicates.
|
||||
for time in times:
|
||||
if '-' not in time:
|
||||
for i in range(7, 20):
|
||||
expanded.append(f'{i:02}00-{time}')
|
||||
else:
|
||||
expanded.append(time)
|
||||
return expanded
|
||||
|
||||
def bridge_stripped(possible_command: str, origin_nick: str) -> str | None:
|
||||
if origin_nick.lower() == BRIDGE_NICKNAME:
|
||||
stripped_user = possible_command.split(':')[1].lstrip()
|
||||
return stripped_user if stripped_user.startswith(TRIGGER) else None
|
||||
else:
|
||||
return possible_command if possible_command.startswith(TRIGGER) else None
|
||||
|
||||
class Server(BaseServer):
|
||||
def extract_valid_command(self, line: Line) -> str | None:
|
||||
me = self.nickname_lower
|
||||
if line.command == "PRIVMSG" and \
|
||||
self.has_channel(line.params[0]) and \
|
||||
line.hostmask is not None and \
|
||||
self.casefold(line.hostmask.nickname) != me and \
|
||||
self.has_user(line.hostmask.nickname):
|
||||
return bridge_stripped(line.params[1], line.hostmask.nickname)
|
||||
|
||||
|
||||
async def line_read(self, line: Line):
|
||||
print(f"{self.name} < {line.format()}")
|
||||
if line.command == "001":
|
||||
print(f"connected to {self.isupport.network}")
|
||||
await self.send(build("JOIN", ["#dgnum-bridge-test"]))
|
||||
|
||||
# In case `!probe_meet <title> <team> <time_1> <time_2> … <time_N> [<timezone>]`
|
||||
if (command := self.extract_valid_command(line)) is not None:
|
||||
text = command.lstrip(TRIGGER)
|
||||
if text.startswith('probe_meet') or text.startswith('pm'):
|
||||
args = text.split(' ')
|
||||
if len(args) < 4:
|
||||
await self.send(build("PRIVMSG", [line.params[0], "usage is !probe_meet <title> <team> <time_1> [<time_2> <time_3> … <time_N>] ; time is in [00-hour-]DDMMYYYY format."]))
|
||||
return
|
||||
|
||||
title, team = args[1], args[2]
|
||||
print(f"creating meet '{title}' for team '{team}'")
|
||||
try:
|
||||
times = expand_times(args[3:])
|
||||
link = await create_meet(title, times)
|
||||
if team not in TEAMS:
|
||||
await self.send(build("PRIVMSG", [line.params[0], f"team {team} does not exist"]))
|
||||
return
|
||||
|
||||
targets = TEAMS[team]
|
||||
ping_mentions = ', '.join(targets)
|
||||
await self.send(build("PRIVMSG", [line.params[0], f'{ping_mentions} {link}']))
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
await self.send(build("PRIVMSG", [line.params[0], "time format is [00-hour-]DDMMYYYY, hour is optional, by default it's 07:00 to 19:00 in Europe/Paris timezone"]))
|
||||
except aiohttp.ClientError as e:
|
||||
print(e)
|
||||
await self.send(build("PRIVMSG", [line.params[0], "failed to create the meet on meet.dgnum.eu, API error, check the logs"]))
|
||||
|
||||
|
||||
async def line_send(self, line: Line):
|
||||
print(f"{self.name} > {line.format()}")
|
||||
|
||||
class Bot(BaseBot):
|
||||
def create_server(self, name: str):
|
||||
return Server(self, name)
|
||||
|
||||
async def main():
|
||||
bot = Bot()
|
||||
for name, host in SERVERS:
|
||||
# For IPv4-only connections.
|
||||
params = ConnectionParams("Takumi", host, 6698)
|
||||
await bot.add_server(name, params)
|
||||
|
||||
await bot.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
|
@ -1,71 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
fetchFromGitHub,
|
||||
poetry-core,
|
||||
aiosqlite,
|
||||
iso8601,
|
||||
callPackage,
|
||||
pytz,
|
||||
ciso8601,
|
||||
orjson,
|
||||
uvloop,
|
||||
aiomysql,
|
||||
asyncmy,
|
||||
asyncpg,
|
||||
psycopg,
|
||||
pydantic,
|
||||
pythonRelaxDepsHook,
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "tortoise-orm";
|
||||
version = "0.21.6";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "tortoise";
|
||||
repo = "tortoise-orm";
|
||||
rev = version;
|
||||
hash = "sha256-Gu7MSJbPjaGUN6tmHwkmx7Bdy/+V1wZjmTCQrTDDPkw=";
|
||||
};
|
||||
|
||||
buildInputs = [ pythonRelaxDepsHook ];
|
||||
|
||||
pythonRelaxDeps = [
|
||||
"aiosqlite"
|
||||
"iso8601"
|
||||
];
|
||||
|
||||
build-system = [ poetry-core ];
|
||||
|
||||
dependencies = [
|
||||
aiosqlite
|
||||
iso8601
|
||||
pydantic
|
||||
(callPackage ./pypika-tortoise.nix { })
|
||||
pytz
|
||||
];
|
||||
|
||||
optional-dependencies = {
|
||||
accel = [
|
||||
ciso8601
|
||||
orjson
|
||||
uvloop
|
||||
];
|
||||
aiomysql = [ aiomysql ];
|
||||
asyncmy = [ asyncmy ];
|
||||
asyncpg = [ asyncpg ];
|
||||
psycopg = [ psycopg ];
|
||||
};
|
||||
|
||||
pythonImportsCheck = [ "tortoise" ];
|
||||
|
||||
meta = {
|
||||
description = "";
|
||||
homepage = "https://github.com/tortoise/tortoise-orm";
|
||||
changelog = "https://github.com/tortoise/tortoise-orm/blob/${src.rev}/CHANGELOG.rst";
|
||||
license = lib.licenses.asl20;
|
||||
maintainers = with lib.maintainers; [ raitobezarius ];
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue