app/mailman-web: create

There's a lot of ugly hacks here, but this has been the state of prod
for months now, so we should reflect that.
Also, this bumps a bunch of workspace deps.

Change-Id: I744e0d3aff27036cfed73416cf442c7d62444a8b
Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1473
Reviewed-by: q3k <q3k@hackerspace.pl>
diff --git a/app/mailman-web/kube/mailman.libsonnet b/app/mailman-web/kube/mailman.libsonnet
new file mode 100644
index 0000000..c71de4e
--- /dev/null
+++ b/app/mailman-web/kube/mailman.libsonnet
@@ -0,0 +1,215 @@
+local kube = import "../../../kube/kube.libsonnet";
+
+{
+    local app = self,
+    local cfg = app.cfg,
+
+    cfg:: {
+        namespace: error "cfg.namespace must be set",
+        webDomain: error "cfg.webDomain must be set",
+        images: {
+            web: "registry.k0.hswaw.net/implr/mailman-web:0.6",
+            # https://github.com/octeep/wireproxy
+            wireproxy: "registry.k0.hswaw.net/implr/wireproxy:1.0.5"
+        },
+        passwords: {
+            postgres: error "cfg.secrets.postgres must be set",
+            mailmanRest: error "cfg.secrets.mailmanRest must be set",
+            mailmanArchiver: error "cfg.secrets.mailmanArchiver must be set",
+        },
+        smtp: {
+            user: "postorius",
+            # from mail server
+            password: error "cfg.smtp.password must be set",
+        },
+        secrets: {
+            djangoSecretKey: error "cfg.secrets.djangoSecretKey must be set",
+        },
+        wg: {
+            peerPubkey: error "cfg.wg.peerPubkey must be set",
+            privkey: error "cfg.wg.privkey must be set",
+            endpoint: error "cfg.wg.endpoint must be set",
+        },
+    },
+
+    env:: {
+        WEB_DOMAIN: cfg.webDomain,
+        BIND_ADDR: "0.0.0.0:8080",
+
+        //DB_HOST: app.postgres.svc.host,
+        DB_HOST: "boston-packets.hackerspace.pl",
+        DB_USER: "mailman",
+        DB_NAME: "mailman-web",
+        DB_PASS: kube.SecretKeyRef(app.config, "postgres-pass"),
+        DB_PORT: "5432",
+
+
+        SMTP_HOST: "mail.hackerspace.pl",
+        SMTP_PORT: "587",
+        SMTP_USER: "postorius",
+        SMTP_PASSWORD: kube.SecretKeyRef(app.config, "smtp-password"),
+
+        SECRET_KEY: kube.SecretKeyRef(app.config, "django-secret-key"),
+        MAILMAN_REST_API_PASS: kube.SecretKeyRef(app.config, 'mailman-api-password'),
+        MAILMAN_ARCHIVER_KEY: kube.SecretKeyRef(app.config, 'mailman-archiver-key'),
+
+    },
+
+    namespace: kube.Namespace(cfg.namespace),
+    local ns = self.namespace,
+
+
+    web: ns.Contain(kube.Deployment("web")) {
+        spec+: {
+            minReadySeconds: 10,
+            replicas: 1,
+            template+: {
+                spec+: {
+                    initContainers_: {
+                        migrate: kube.Container("migrate") {
+                            image: cfg.images.web,
+                            env_: app.env,
+                            args: [
+                                "manage", "migrate",
+                            ],
+                        },
+                    },
+                    volumes_: {
+                        config: kube.SecretVolume(app.wireproxyConfig),
+                    },
+                    containers_: {
+                        default: kube.Container("default") {
+                            image: cfg.images.web,
+                            env_: app.env,
+                            args: ["serve"],
+                            ports_: {
+                                web: { containerPort: 8080 },
+                            },
+                            # readinessProbe: {
+                            #     httpGet: {
+                            #         path: "/",
+                            #         port: "web",
+                            #     },
+                            #     failureThreshold: 10,
+                            #     periodSeconds: 5,
+                            # },
+                            resources: {
+                                requests: {
+                                    cpu: "250m",
+                                    memory: "1024M",
+                                },
+                                limits: {
+                                    cpu: "1",
+                                    memory: "1024M",
+                                },
+                            },
+                        },
+                        wireproxy: kube.Container("wireproxy") {
+                            image: cfg.images.wireproxy,
+                            resources: {
+                                requests: {
+                                    cpu: "100m",
+                                    memory: "64M",
+                                },
+                                limits: {
+                                    cpu: "200m",
+                                    memory: "128M",
+                                },
+                            },
+                            volumeMounts_: {
+                                config: { mountPath: "/etc/wireproxy/config", subPath: "config" }
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    },
+
+    local manifestIniMultisection(sname, values) = std.join('\n',
+        [std.manifestIni({
+                sections: {
+                    [sname]: i,
+            }}) for i in values]),
+    wireproxyConfig: ns.Contain(kube.Secret("wireproxy-config")) {
+        data: {
+            config: std.base64(std.manifestIni({
+                sections: {
+                    Interface: {
+                        Address: cfg.wg.address,
+                        PrivateKey: cfg.wg.privkey,
+                    },
+                    Peer: {
+                        PublicKey: cfg.wg.peerPubkey,
+                        Endpoint: cfg.wg.endpoint,
+                    },
+
+                },
+            }) + manifestIniMultisection("TCPClientTunnel", [
+                # {
+                #     # postgres
+                #     ListenPort: 5432,
+                #     Target: "localhost:5432",
+                # },
+                {
+                    # mailman core api
+                    BindAddress: "127.0.0.1:8001",
+                    Target: "172.17.1.1:8001",
+                },
+            ])),
+        },
+    },
+
+
+    svcWeb: ns.Contain(kube.Service("web")) {
+        target_pod: app.web.spec.template,
+        spec+: {
+            # hax
+            type: "LoadBalancer",
+            externalTrafficPolicy: "Local",
+        },
+    },
+
+
+    #ingress: ns.Contain(kube.Ingress("mailman")) {
+    #    metadata+: {
+    #        annotations+: {
+    #            "kubernetes.io/tls-acme": "true",
+    #            "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
+    #            "nginx.ingress.kubernetes.io/proxy-body-size": "0",
+    #        },
+    #    },
+    #    spec+: {
+    #        tls: [
+    #            {
+    #                hosts: [cfg.webDomain],
+    #                secretName: "mailman-ingress-tls",
+    #            },
+    #        ],
+    #        rules: [
+    #            {
+    #                host: cfg.webDomain,
+    #                http: {
+    #                    paths: [
+    #                        { path: "/", backend: app.svcWeb.name_port },
+    #                        //{ path: "/static/", backend: app.svcStatic.name_port },
+    #                    ],
+    #                },
+    #            },
+    #        ],
+    #    },
+    #},
+
+    config: ns.Contain(kube.Secret("config")) {
+        data_: {
+            "postgres-pass": cfg.passwords.postgres,
+            "django-secret-key": cfg.secrets.djangoSecretKey,
+
+            "smtp-password": cfg.smtp.password,
+
+            "mailman-api-password": cfg.mailmanCore.mailmanApiPass,
+            "mailman-archiver-key": cfg.mailmanCore.mailmanArchiverKey,
+
+        },
+    },
+}