app/{gerrit,bazel-cache} -> devtools/

Change-Id: I2a98f33c76a59392e644579a1f7064a7c8eaec7c
diff --git a/devtools/gerrit/kube/gerrit.libsonnet b/devtools/gerrit/kube/gerrit.libsonnet
new file mode 100644
index 0000000..e36c7fa
--- /dev/null
+++ b/devtools/gerrit/kube/gerrit.libsonnet
@@ -0,0 +1,212 @@
+local kube = import "../../../kube/kube.libsonnet";
+
+{
+    local gerrit = self,
+    local cfg = gerrit.cfg,
+
+    cfg:: {
+        namespace: error "namespace must be set",
+        appName: "gerrit",
+        prefix: "", # if set, should be 'foo-'
+        domain: error "domain must be set",
+        identity: error "identity (UUID) must be set",
+
+        // The secret must contain a key named 'secure.config' containing (at least):
+        // [auth]
+        //      registerEmailPrivateKey = <random>
+        // [plugin "gerrit-oauth-provider-warsawhackerspace-oauth"]
+        //      client-id = foo
+        //      client-secret = bar
+        // [sendemail]
+        //      smtpPass = foo
+        // [receiveemail]
+        //      password = bar
+        secureSecret: error "secure secret name must be set",
+
+        storageClass: error "storage class must be set",
+        storageSize: {
+            git: "50Gi", // Main storage for repositories and NoteDB.
+            index: "10Gi", // Secondary Lucene index
+            cache: "10Gi", // H2 cache databases
+            db: "1Gi", // NoteDB is used, so database is basically empty (H2 accountPatchReviewDatabase)
+            etc: "1Gi", // Random site stuff.
+        },
+
+        email: {
+            server: "mail.hackerspace.pl",
+            username: "gerrit",
+            address: "gerrit@hackerspace.pl",
+        },
+
+        tag: "3.0.0-r7",
+        image: "registry.k0.hswaw.net/devtools/gerrit:" + cfg.tag,
+        resources: {
+            requests: {
+                cpu: "100m",
+                memory: "500Mi",
+            },
+            limits: {
+                cpu: "1",
+                memory: "2Gi",
+            },
+        },
+    },
+
+    name(suffix):: cfg.prefix + suffix,
+
+    metadata(component):: {
+        namespace: cfg.namespace,
+        labels: {
+            "app.kubernetes.io/name": cfg.appName,
+            "app.kubernetes.io/managed-by": "kubecfg",
+            "app.kubernetes.io/component": "component",
+        },
+    },
+
+    configmap: kube.ConfigMap(gerrit.name("gerrit")) {
+        metadata+: gerrit.metadata("configmap"),
+        data: {
+            "gerrit.config": |||
+                [gerrit]
+                    basePath  = git
+                    canonicalWebUrl = https://%(domain)s/
+                    serverId = %(identity)s
+
+                [sshd]
+                    advertisedAddress  = %(domain)s
+
+                [container]
+                    javaOptions = -Djava.security.edg=file:/dev/./urandom
+
+                [auth]
+                    type = OAUTH
+                    gitBasicAuthPolicy = HTTP
+
+                [httpd]
+                    listenUrl = proxy-http://*:8080
+
+                [sshd]
+                    advertisedAddress = %(domain)s
+
+                [user]
+                    email = %(emailAddress)s
+
+                [sendemail]
+                    enable = true
+                    from = MIXED
+                    smtpServer = %(emailServer)s
+                    smtpServerPort = 465
+                    smtpEncryption = ssl
+                    smtpUser = %(emailUser)s
+
+                [receiveemail]
+                    protocol = IMAP
+                    host = %(emailServer)s
+                    username = %(emailUser)s
+                    encryption = TLS
+                    enableImapIdle = true
+
+            ||| % {
+                domain: cfg.domain,
+                identity: cfg.identity,
+                emailAddress: cfg.email.address,
+                emailServer: cfg.email.server,
+                emailUser: cfg.email.username,
+            },
+        },
+    },
+
+    volumes: {
+        [name]: kube.PersistentVolumeClaim(gerrit.name(name)) {
+            metadata+: gerrit.metadata("storage"),
+            spec+: {
+                storageClassName: cfg.storageClassName,
+                accessModes: ["ReadWriteOnce"],
+                resources: {
+                    requests: {
+                        storage: cfg.storageSize[name],
+                    },
+                },
+            },
+        }
+        for name in ["etc", "git", "index", "cache", "db"]
+    },
+
+    local volumeMounts = {
+        [name]: { mountPath: "/var/gerrit/%s" % name }
+        for name in ["etc", "git", "index", "cache", "db"]
+    } {
+        // ConfigMap gets mounted here
+        config: { mountPath: "/var/gerrit-config" },
+        // SecureSecret gets mounted here
+        secure: { mountPath: "/var/gerrit-secure" },
+    },
+    deployment: kube.Deployment(gerrit.name("gerrit")) {
+        metadata+: gerrit.metadata("deployment"),
+        spec+: {
+            replicas: 1,
+            template+: {
+                spec+: {
+                    securityContext: {
+                        fsGroup: 1000, # gerrit uid
+                    },
+                    volumes_: {
+                        config: kube.ConfigMapVolume(gerrit.configmap),
+                        secure: { secret: { secretName: cfg.secureSecret} },
+                    } {
+                        [name]: kube.PersistentVolumeClaimVolume(gerrit.volumes[name])
+                        for name in ["etc", "git", "index", "cache", "db"]
+                    },
+                    containers_: {
+                        gerrit: kube.Container(gerrit.name("gerrit")) {
+                            image: cfg.image,
+                            ports_: {
+                                http: { containerPort: 8080 },
+                                ssh: { containerPort: 29418 },
+                            },
+                            resources: cfg.resources,
+                            volumeMounts_: volumeMounts,
+                        },
+                    },
+                },
+            },
+        },
+    },
+
+    svc: kube.Service(gerrit.name("gerrit")) {
+        metadata+: gerrit.metadata("service"),
+        target_pod:: gerrit.deployment.spec.template,
+        spec+: {
+            ports: [
+                { name: "http", port: 80, targetPort: 8080, protocol: "TCP" },
+                { name: "ssh", port: 22, targetPort: 29418, protocol: "TCP" },
+            ],
+            type: "ClusterIP",
+        },
+    },
+
+    ingress: kube.Ingress(gerrit.name("gerrit")) {
+        metadata+: gerrit.metadata("ingress") {
+            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: gerrit.name("acme") },
+            ],
+            rules: [
+                {
+                    host: cfg.domain, 
+                    http: {
+                        paths: [
+                            { path: "/", backend: gerrit.svc.name_port },
+                        ],
+                    },
+                }
+            ],
+        },
+    },
+}