hswaw/oodviewer: init

This brings oodviewer into k0.

oodviewer started as a py2/flask script running on q3k's personal infra,
which is now being turned down.

This is a rewrite of that script into similarly mediocre Go, conforming
to the exact same mediocre JSON API and spartan HTML interface.

This also deploys it into k0 in the oodviewer-prod namespace. It's
already running, but the 'oodviewer.q3k.me' TTL has to expire before it
begins handling traffic.

Change-Id: Ieef1b0f8f0c60e6fa5dbe7701e0a07a4257f99ce
diff --git a/hswaw/oodviewer/prod.jsonnet b/hswaw/oodviewer/prod.jsonnet
new file mode 100644
index 0000000..e06b368
--- /dev/null
+++ b/hswaw/oodviewer/prod.jsonnet
@@ -0,0 +1,85 @@
+// Production deployment of oodviewer.q3k.me.
+//
+// See README.md for more information.
+
+local kube = import "../../kube/kube.libsonnet";
+
+{
+    local top = self,
+    local cfg = self.cfg,
+    ns: kube.Namespace("oodviewer-prod"),
+
+    cfg:: {
+        dbUser: "ood",
+        dbPass: std.split(importstr "secrets/plain/postgres-pass", "\n")[0],
+        dbHost: "hackerspace.pl",
+        dbName: "ood",
+        postgresConnectionString: "postgres://%s:%s@%s/%s?sslmode=disable" % [cfg.dbUser, cfg.dbPass, cfg.dbHost, cfg.dbName],
+
+        image: "registry.k0.hswaw.net/q3k/oodviewer:315532800-937278cfb82e41dd2d2010cbd184834b3392116b",
+        domain: "oodviewer.q3k.me",
+    },
+
+    secret: top.ns.Contain(kube.Secret("oodviewer")) {
+        data_: {
+            "postgres": cfg.postgresConnectionString,
+        },
+    },
+
+    deploy: top.ns.Contain(kube.Deployment("oodviewer")) {
+        spec+: {
+            replicas: 3,
+            template+: {
+                spec+: {
+                    containers_: {
+                        default: kube.Container("default") {
+                            image: cfg.image,
+                            command: [
+                                "/hswaw/oodviewer",
+                                "-listen", "0.0.0.0:8080",
+                                "-postgres", "$(POSTGRES)",
+                            ],
+                            env_: {
+                                POSTGRES: kube.SecretKeyRef(top.secret, "postgres"),
+                            },
+                            resources: {
+                                requests: { cpu: "0.01", memory: "64M" },
+                                limits: { cpu: "1", memory: "256M" },
+                            },
+                            ports_: {
+                                http: { containerPort: 8080 },
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    },
+
+    service: top.ns.Contain(kube.Service("oodviewer")) {
+        target_pod:: top.deploy.spec.template,
+    },
+
+    ingress: top.ns.Contain(kube.Ingress("oodviewer")) {
+        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.domain ], secretName: "oodviewer-tls" } ],
+            rules: [
+                {
+                    host: cfg.domain,
+                    http: {
+                        paths:  [
+                            { path: "/", backend: top.service.name_port },
+                        ],
+                    },
+                },
+            ],
+        },
+    }
+}