blob: 209e8553aa4823de4cf847eb51d82bd03e021297 [file] [log] [blame]
local kube = import "../../../kube/kube.libsonnet";
{
AppServiceTelegram(name):: {
local bridge = self,
local cfg = bridge.cfg,
cfg:: {
metadata: {},
// Whether the bootstrap job should be created/updated. Kubernetes
// doesn't like changing the configuration of jobs, so once this
// appservice has been set up, this flag should be flipped to
// false.
bootstrapJob: true,
image: error "image must be set",
storageClassName: error "storageClassName must be set",
// Data that will be serialized into the appservice's config.yaml.
// This is taken straight from a YAML that was generated by
// dock.mau.dev/tulir/mautrix-telegram:v0.8.2. We override here
// fields that we know are strictly necessary to be configured when
// instantiating this template.
config: (std.native("parseYaml")(importstr "appservice/appservice-telegram.yaml")[0]) + {
homeserver+: {
address: error "homeserver.address must be set",
domain: error "homeserver.domain must be set",
},
appservice+: {
address: bridge.svc.http_url,
// We disable this. I have no idea what it does, but it
// wants a secret. ~q3k
provisioning+: {
enabled: false,
shared_secret: if self.enabled then error "appservice.provisioning.shared_secret must be set" else "hackme",
},
id: error "appservice.id must be set",
as_token: "This value is generated when generating the registration",
hs_token: "This value is generated when generating the registration",
},
telegram+: {
api_id: error "telegram.api_id must be set",
api_hash: error "telegram.api_hash must be set",
bot_token: error "telegram.bot_token must be set",
},
bridge+: {
permissions: {
'*': "relaybot",
},
},
},
},
config: kube.Secret("appservice-telegram-%s" % [name]) {
metadata+: cfg.metadata,
data: {
"config.yaml": std.base64(std.manifestYamlDoc(cfg.config)),
},
},
dataVolume: kube.PersistentVolumeClaim("appservice-telegram-%s" % [name]) {
metadata+: cfg.metadata,
storage: "10Gi",
storageClass: cfg.storageClassName,
},
bootstrapJob: if cfg.bootstrapJob then (kube.Job("appservice-telegram-%s-bootstrap" % [name]) {
metadata+: cfg.metadata {
labels: {
"job-name": "appservice-telegram-%s-bootstrap" % [name],
},
},
spec+: {
template+: {
spec+: {
volumes_: {
config: kube.SecretVolume(bridge.config),
},
containers_: {
bootstrap: kube.Container("appservice-telegram-%s-bootstrap" % [name]) {
image: cfg.image,
command: [
"sh", "-c",
"python3 -m mautrix_telegram -g -c /config/config.yaml -r /tmp/registration.yaml && echo SNIPSNIP && cat /tmp/registration.yaml",
],
volumeMounts_: {
config: { mountPath: "/config" },
},
},
},
},
},
},
}) else {},
deployment: kube.Deployment("appservice-telegram-%s" % [name]) {
metadata+: cfg.metadata,
spec+: {
replicas: 1,
template+: {
spec+: {
volumes_: {
config: kube.SecretVolume(bridge.config),
data: kube.PersistentVolumeClaimVolume(bridge.dataVolume),
registration: { secret: { secretName: "appservice-telegram-%s-registration" % [name] } },
},
initContainers: [
// This container takes the stateless config from the Secret, and
// updates it with the registration secrets from the registration token.
kube.Container("generate-config") {
volumeMounts_: {
config: { mountPath: "/config", },
registration: { mountPath: "/registration", },
data: { mountPath: "/data" },
},
image: "alpine:3.13",
command: [
"sh", "-c", |||
set -e -x
apk add --no-cache yq
cp /config/config.yaml /data/config.yaml
yq w -i /data/config.yaml appservice.as_token $(yq r /registration/registration.yaml as_token)
yq w -i /data/config.yaml appservice.hs_token $(yq r /registration/registration.yaml hs_token)
|||
],
},
],
containers_: {
appserviceIrc: kube.Container("appservice-telegram-%s" % [name]) {
image: cfg.image,
command: [
"sh", "-c", |||
alembic -x config=/data/config.yaml upgrade head
python3 -m mautrix_telegram -n -c /data/config.yaml
|||
],
ports_: {
http: { containerPort: 29317 },
},
volumeMounts_: {
data: { mountPath: "/data" },
},
},
},
},
},
},
},
svc: kube.Service("appservice-telegram-%s" % [name]) {
metadata+: cfg.metadata,
target:: bridge.deployment,
},
},
}