matrix: add Telegram bridge appservice.

Configuring this one is a bit different from appservice-irc. Notably,
there's no way to give it a registration.yaml to overlay on top of a
config, se we end up using an init container with yq to do that for us.

Also, I had to manually copy the regsitration.yaml in synapse, from
/appservices/telegram-prod/registration.yaml to
/data/appservices/telegram-prod.jsonnet, in order to make it work with
the synapse docker start magic. :/

Otherwise, this is deployed and seems to be working.

Change-Id: Id747a0e310221855556c1d280439376f0c4e5ed6
diff --git a/app/matrix/prod.jsonnet b/app/matrix/prod.jsonnet
index cf68738..66be5ea 100644
--- a/app/matrix/prod.jsonnet
+++ b/app/matrix/prod.jsonnet
@@ -2,12 +2,25 @@
 # This needs a secret provisioned, create with:
 #    kubectl -n matrix create secret generic synapse --from-literal=postgres_password=$(pwgen 24 1) --from-literal=macaroon_secret_key=$(pwgen 32 1) --from-literal=registration_shared_secret=$(pwgen 32 1)
 #    kubectl -n matrix create secret generic oauth2-cas-proxy --from-literal=oauth2_secret=...
+#
+# Sequencing appservices is fun. The appservice needs to run first (for
+# instance, via a bootstrap job), and on startup it will spit out a
+# registration file.  This registration file then needs to be fed to synapse -
+# this is done via specialy named secrets (appservice-X-registration, for X key
+# in the appservices object).
+#
+# For appservice-irc instances, you can use this oneliner magic to get the
+# registration YAML from logs.
 #    kubectl -n matrix create secret generic appservice-irc-freenode-registration --from-file=registration.yaml=<(kubectl logs -n matrix $(kubectl get pods -n matrix --selector=job-name=appservice-irc-freenode-bootstrap --output=jsonpath='{.items[*].metadata.name}') | tail -n +4 | sed -r 's/(.*aliases:.*)/      group_id: "+freenode:hackerspace.pl"\n\1/')
+#
+# For appservice-telegram instances, you can use this oneliner magic:
+#    kubectl -n matrix create secret generic appservice-telegram-prod-registration --from-file=registration.yaml=<(kubectl -n matrix logs job/appservice-telegram-prod-bootstrap | grep -A 100 SNIPSNIP | grep -v SNIPSNIP)
 
 local kube = import "../../kube/kube.libsonnet";
 local postgres = import "../../kube/postgres.libsonnet";
 
 local irc = import "appservice-irc.libsonnet";
+local telegram = import "appservice-telegram.libsonnet";
 
 {
     local app = self,
@@ -16,13 +29,14 @@
         namespace: "matrix",
         domain: "matrix.hackerspace.pl",
         serverName: "hackerspace.pl",
-        storageClassName: "waw-hdd-paranoid-2",
-        storageClassName3: "waw-hdd-redundant-3",
+        storageClassName: "waw-hdd-redundant-3",
 
         synapseImage: "matrixdotorg/synapse:v1.17.0",
         riotImage: "vectorim/riot-web:v1.7.1",
         casProxyImage: "registry.k0.hswaw.net/q3k/oauth2-cas-proxy:0.1.4",
         appserviceIRCImage: "matrixdotorg/matrix-appservice-irc:release-0.17.1",
+        # That's v0.8.2 - we just don't trust that host to not re-tag images.
+        appserviceTelegramImage: "dock.mau.dev/tulir/mautrix-telegram@sha256:9e68eaa80c9e4a75d9a09ec92dc4898b12d48390e01efa4de40ce882a6f7e330"
     },
 
     metadata(component):: {
@@ -44,7 +58,7 @@
             username: "synapse",
             prefix: "waw3-",
             password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
-            storageClassName: cfg.storageClassName3,
+            storageClassName: cfg.storageClassName,
             storageSize: "100Gi",
         },
     },
@@ -52,7 +66,7 @@
     dataVolume: kube.PersistentVolumeClaim("synapse-data-waw3") {
         metadata+: app.metadata("synapse-data"),
         spec+: {
-            storageClassName: cfg.storageClassName3,
+            storageClassName: cfg.storageClassName,
             accessModes: [ "ReadWriteOnce" ],
             resources: {
                 requests: {
@@ -223,11 +237,18 @@
         target_pod:: app.riotDeployment.spec.template,
     },
 
+    // Any appservice you add here will require an appservice-X-registration
+    // secret containing a registration.yaml file. Adding something to this
+    // dictionary will cause Synapse to not start until that secret is
+    // available - so change things carefully!
+    // If bootstrapping a new appservice, just keep it out of this dictionary
+    // until it spits you a registration YAML and you feed that to a secret.
     appservices: {
         "irc-freenode": irc.AppServiceIrc("freenode") {
             cfg+: {
                 image: cfg.appserviceIRCImage,
-                storageClassName: cfg.storageClassName,
+                // TODO(q3k): move this appservice to waw-hdd-redundant-3
+                storageClassName: "waw-hdd-paranoid-2",
                 metadata: app.metadata("appservice-irc-freenode"),
                 // TODO(q3k): add labels to blessed nodes
                 nodeSelector: {
@@ -250,6 +271,34 @@
                 },
             },
         },
+        "telegram-prod": telegram.AppServiceTelegram("prod") {
+            cfg+: {
+                image: cfg.appserviceTelegramImage,
+                storageClassName: cfg.storageClassName,
+                metadata: app.metadata("appservice-telegram-prod"),
+
+                config+: {
+                    homeserver+: {
+                        address: "https://%s" % [cfg.domain],
+                        domain: cfg.serverName,
+                    },
+                    appservice+: {
+                        id: "telegram",
+                    },
+                    telegram+: {
+                        api_id: (std.split(importstr "secrets/plain/appservice-telegram-prod-api-id", "\n"))[0],
+                        api_hash: (std.split(importstr "secrets/plain/appservice-telegram-prod-api-hash", "\n"))[0],
+                        bot_token: (std.split(importstr "secrets/plain/appservice-telegram-prod-token", "\n"))[0],
+                    },
+                    bridge+: {
+                        permissions+: {
+                            "hackerspace.pl": "puppeting",
+                            "@q3k:hackerspace.pl": "admin",
+                        },
+                    },
+                },
+            },
+        },
     },
 
     ingress: kube.Ingress("matrix") {