feat: implement getmail runner script and update email fetching configuration

This commit is contained in:
2025-10-06 23:36:50 +02:00
parent 7f9a64b0ed
commit 84c8288f8a
5 changed files with 157 additions and 58 deletions
-2
View File
@@ -48,8 +48,6 @@ module "mail" {
relay_smtp_username = var.scaleway_project_id relay_smtp_username = var.scaleway_project_id
relay_smtp_password = local.mail_app_api_secret_key relay_smtp_password = local.mail_app_api_secret_key
fetch_emails_schedule = local.fetch_emails_schedule
mail_crypt_private_key = var.mail_crypt_private_key mail_crypt_private_key = var.mail_crypt_private_key
mail_crypt_public_key = var.mail_crypt_public_key mail_crypt_public_key = var.mail_crypt_public_key
+4
View File
@@ -101,6 +101,10 @@ locals {
secret_name = "mail-tls" secret_name = "mail-tls"
} }
} }
getmail_runner_script = file("${path.module}/resources/getmail/runner.py")
checksum_getmail_runner_script = sha256(local.getmail_runner_script)
getmail_fetch_interval_seconds = coalesce(var.getmail_fetch_interval_seconds, 120)
} }
data "external" "password_hasher" { data "external" "password_hasher" {
+79 -27
View File
@@ -8,56 +8,96 @@ resource "kubernetes_secret" "getmail_config" {
type = "Opaque" type = "Opaque"
} }
resource "kubernetes_cron_job_v1" "fetch_emails" { resource "kubernetes_config_map_v1" "getmail_runner" {
metadata {
name = "getmail-runner"
namespace = kubernetes_namespace.mail.metadata[0].name
}
data = {
"runner.py" = local.getmail_runner_script
}
}
resource "kubernetes_deployment_v1" "fetch_emails" {
metadata { metadata {
namespace = kubernetes_namespace.mail.metadata[0].name namespace = kubernetes_namespace.mail.metadata[0].name
name = "fetch-emails" name = "fetch-emails"
}
spec {
schedule = var.fetch_emails_schedule
job_template {
metadata {
name = "fetch-emails"
}
spec {
backoff_limit = 1
parallelism = 1
completions = 1
active_deadline_seconds = 300
template {
metadata {
labels = { labels = {
app = "fetch-emails" app = "fetch-emails"
} }
} }
spec {
replicas = 1
selector {
match_labels = {
app = "fetch-emails"
}
}
template {
metadata {
labels = {
app = "fetch-emails"
}
annotations = {
"checksum/runner-script" = local.checksum_getmail_runner_script
}
}
spec { spec {
container { container {
name = "getmail" name = "getmail"
image = "a13labs/getmail6:${var.getmail_tag}" image = "a13labs/getmail6:${var.getmail_tag}"
args = concat(["--getmaildir", "/var/getmail"], flatten([for job in local.getmail_jobs : ["-r", "/getmail/getmailrc_${job.name}"]])) command = ["python3", "/runner/runner.py"]
env {
name = "FETCH_INTERVAL_SECONDS"
value = local.getmail_fetch_interval_seconds
}
volume_mount { volume_mount {
name = "getmail-config" name = "getmail-config"
mount_path = "/getmail" mount_path = "/getmail"
read_only = true read_only = true
} }
security_context {
run_as_user = 1000
run_as_group = 1000
}
volume_mount { volume_mount {
name = "getmail-cache" name = "getmail-cache"
mount_path = "/var/getmail" mount_path = "/var/getmail"
} }
volume_mount {
name = "runner-script"
mount_path = "/runner"
read_only = true
}
volume_mount {
name = "tmp"
mount_path = "/tmp"
} }
restart_policy = "Never" security_context {
run_as_user = 1000
run_as_group = 1000
read_only_root_filesystem = true
}
# Basic liveness (process must still be running)
liveness_probe {
exec {
command = ["bash", "-c", "pgrep -f runner.py > /dev/null"]
}
initial_delay_seconds = 30
period_seconds = 30
}
resources {
requests = {
cpu = "20m"
memory = "64Mi"
}
limits = {
cpu = "200m"
memory = "256Mi"
}
}
}
volume { volume {
name = "getmail-config" name = "getmail-config"
@@ -69,7 +109,6 @@ resource "kubernetes_cron_job_v1" "fetch_emails" {
key = "getmailrc_${items.value.name}" key = "getmailrc_${items.value.name}"
path = "getmailrc_${items.value.name}" path = "getmailrc_${items.value.name}"
} }
} }
} }
} }
@@ -80,9 +119,22 @@ resource "kubernetes_cron_job_v1" "fetch_emails" {
path = local.getmail_path path = local.getmail_path
} }
} }
volume {
name = "runner-script"
config_map {
name = kubernetes_config_map_v1.getmail_runner.metadata[0].name
items {
key = "runner.py"
path = "runner.py"
} }
} }
} }
volume {
name = "tmp"
empty_dir {}
}
}
} }
} }
} }
@@ -0,0 +1,44 @@
import os, signal, subprocess, time, sys
import logging
INTERVAL = int(os.getenv("FETCH_INTERVAL_SECONDS", "120"))
GETMAILDIR = "/var/getmail"
CONFIG_DIR = "/getmail"
JOBS = [f for f in os.listdir(CONFIG_DIR) if f.startswith("getmailrc_")]
logging.basicConfig(
level=logging.INFO,
format="[%(asctime)s] %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
stop = False
def handle(sig, frame):
global stop
logging.info(f"Received signal {sig}, stopping runner...")
stop = True
for s in (signal.SIGINT, signal.SIGTERM):
signal.signal(s, handle)
def run_once():
args = ["getmail", "--getmaildir", GETMAILDIR]
for job in JOBS:
args += ["-r", f"{CONFIG_DIR}/{job}"]
logging.info(f"Running getmail with jobs: {JOBS}")
try:
rc = subprocess.call(args, stdout=sys.stdout, stderr=sys.stderr)
logging.info(f"getmail exited with code {rc}")
return rc
except Exception as e:
logging.error(f"Error running getmail: {e}")
return 1
logging.info("Starting getmail runner...")
while not stop:
rc = run_once()
for _ in range(INTERVAL):
if stop: break
time.sleep(1)
logging.info("Exiting getmail runner.")
sys.exit(0)
+4 -3
View File
@@ -46,9 +46,10 @@ variable "relay_smtp_password" {
sensitive = true sensitive = true
} }
variable "fetch_emails_schedule" { variable "getmail_fetch_interval_seconds" {
description = "The cron schedule for fetching emails" description = "The interval for fetching emails (in seconds)"
type = string type = number
default = 120
} }
variable "getmail_tag" { variable "getmail_tag" {