devtools: add sourcegraph

Change-Id: Ic3c40768c761e598e0f42b17a4b9f0d4ebcb2bb2
diff --git a/devtools/kube/sourcegraph.libsonnet b/devtools/kube/sourcegraph.libsonnet
new file mode 100644
index 0000000..9e2454d
--- /dev/null
+++ b/devtools/kube/sourcegraph.libsonnet
@@ -0,0 +1,101 @@
+local mirko = import "../../kube/mirko.libsonnet";
+local kube = import "../../kube/kube.libsonnet";
+
+// Deploy SourceGraph, a code serach tool. Its configuration is fully managed
+// within sourcegraph itself, including user accounts.
+
+{
+    cfg:: {
+        image: "sourcegraph/server:3.17.1",
+        publicFQDN: error "public FQDN must be set",
+        storageClassName: "waw-hdd-redundant-3",
+    },
+
+    component(cfg, env):: mirko.Component(env, "sourcegraph") {
+        local sourcegraph = self,
+        cfg+: {
+            image: cfg.image,
+            volumes+: {
+                data: kube.PersistentVolumeClaimVolume(sourcegraph.pvc.data),
+                etc: kube.PersistentVolumeClaimVolume(sourcegraph.pvc.etc),
+            },
+            securityContext: {
+                runAsUser: 0,
+                fsGroup: 70,
+            },
+            container: sourcegraph.Container("main") {
+                volumeMounts_+: {
+                    data: { mountPath: "/var/opt/sourcegraph" },
+                    etc: { mountPath: "/etc/sourcegraph" },
+                },
+                resources: {
+                    requests: {
+                        cpu: "100m",
+                        memory: "1Gi",
+                    },
+                    limits: {
+                        cpu: "1",
+                        memory: "2Gi",
+                    },
+                },
+            },
+            ports+: {
+                publicHTTP: {
+                    public: {
+                        port: 7080,
+                        dns: cfg.publicFQDN,
+                        // Authenticate as 'Anonymous' user by default. This is done in tandem
+                        // with Sourcegraphs authenticate-by-http-header feature, and is a
+                        // workaround for the lack of a public view in the self-hosted free
+                        // version of Sourcegraph.
+                        // https://twitter.com/sqs/status/1272659451292422144
+                        setHeaders: ["X-Forwarded-User Anonymous"],
+                    },
+                },
+            },
+            extraPaths: [
+                {
+                    // Redirect anonymous user settings to a service that doesn't
+                    // have any endpoints/backends.
+                    path: "/users/Anonymous/settings",
+                    backend: { serviceName: sourcegraph.blocksvc.metadata.name, servicePort: 8080 },
+                },
+            ],
+        },
+
+        blocksvc: kube.Service(sourcegraph.makeName("blocksvc")) {
+            metadata+: sourcegraph.metadata,
+            spec+: {
+                selector: null,
+                ports: [{ port: 2137, targetPort: 2137 }],
+            },
+        },
+
+        pvc: {
+            data: kube.PersistentVolumeClaim(sourcegraph.makeName("data")) {
+                metadata+: sourcegraph.metadata,
+                spec+: {
+                    storageClassName: cfg.storageClassName,
+                    accessModes: [ "ReadWriteOnce" ],
+                    resources: {
+                        requests: {
+                            storage: "40Gi",
+                        },
+                    },
+                },
+            },
+            etc: kube.PersistentVolumeClaim(sourcegraph.makeName("etc")) {
+                metadata+: sourcegraph.metadata,
+                spec+: {
+                    storageClassName: cfg.storageClassName,
+                    accessModes: [ "ReadWriteOnce" ],
+                    resources: {
+                        requests: {
+                            storage: "4Gi",
+                        },
+                    },
+                },
+            },
+        },
+    }
+}