Add workaround allowing to use NFS-mounts for git repositories

Using NFS volumes as Read-Write-Many volumes for the git repositories,
did not work out of the box for two reasons:

- Kubernetes is not able to mount the volume with the group given in
  the fsGroup setting. The volume was thus owned by root:root.
- The user-/group-ID mapping did not correctly work and the IDs were
  mapped to nobody.

This is now fixed by the following changes:

- The init job running before the Gerrit replica starts now has an init
  container that will chown the mounted volume to ensure that the user
  used by Gerrit has access to the repositories.
- All containers mounting the NFS-share now get a custom idmapd.conf file
  that sets the idDomain configured in the helm chart to ensure the
  correct ID mapping.

Change-Id: Ib39d4d98bb8e142cce4dd3f00b30ed3be127e9d4
diff --git a/helm-charts/gerrit-replica/README.md b/helm-charts/gerrit-replica/README.md
index ae361d0..93a48f4 100644
--- a/helm-charts/gerrit-replica/README.md
+++ b/helm-charts/gerrit-replica/README.md
@@ -127,11 +127,13 @@
 
 ### Storage for Git repositories
 
-| Parameter                               | Description                                     | Default              |
-|-----------------------------------------|-------------------------------------------------|----------------------|
-| `gitRepositoryStorage.externalPVC.use`  | Whether to use a PVC deployed outside the chart | `false`              |
-| `gitRepositoryStorage.externalPVC.name` | Name of the external PVC                        | `git-filesystem-pvc` |
-| `gitRepositoryStorage.size`             | Size of the volume storing the Git repositories | `5Gi`                |
+| Parameter                               | Description                                                                | Default              |
+|-----------------------------------------|----------------------------------------------------------------------------|----------------------|
+| `gitRepositoryStorage.externalPVC.use`  | Whether to use a PVC deployed outside the chart                            | `false`              |
+| `gitRepositoryStorage.externalPVC.name` | Name of the external PVC                                                   | `git-filesystem-pvc` |
+| `gitRepositoryStorage.size`             | Size of the volume storing the Git repositories                            | `5Gi`                |
+| `gitRepositoryStorage.nfs.enabled`      | Whether the volume used is an NFS-volume                                   | `false`              |
+| `gitRepositoryStorage.nfs.idDomain`     | The ID-domain that should be used to map user-/group-IDs for the NFS mount | `localdomain.com`    |
 
 If the git repositories should be persisted even if the chart is deleted and in
 a way that the volume containing them can be mounted by the reinstalled chart,
@@ -139,6 +141,13 @@
 the external PVC, set `gitRepositoryStorage.externalPVC.enabled` to `true` and
 give the name of the PVC under `gitRepositoryStorage.externalPVC.name`.
 
+Using an NFS mount in Kubernetes can be a bit tricky. To make it work, this chart
+provides a workaround that can be activated by setting `gitRepositoryStorage.nfs.enabled`
+to `true`. One thing it does, is to provide a `idmapd.conf` file that configures
+the ID domain set in `gitRepositoryStorage.nfs.idDomain`. It will also add an
+init-container to the init-job that will ensure that the directory that will
+contain the repositories is owned by the correct user.
+
 ### Istio
 
 Istio can be used as an alternative to Kubernetes Ingresses to manage the traffic
diff --git a/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml b/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
index fa607a7..de71e78 100644
--- a/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
+++ b/helm-charts/gerrit-replica/templates/gerrit-replica.deployment.yaml
@@ -110,6 +110,11 @@
           mountPath: "/var/gerrit"
         - name: git-filesystem
           mountPath: "/var/mnt/git"
+        {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+        - name: nfs-config
+          mountPath: "/etc/idmapd.conf"
+          subPath: idmapd.conf
+        {{- end }}
         - name: gerrit-init-config
           mountPath: "/var/config/gerrit-init.yaml"
           subPath: gerrit-init.yaml
@@ -147,6 +152,11 @@
           mountPath: "/var/gerrit"
         - name: git-filesystem
           mountPath: "/var/mnt/git"
+        {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+        - name: nfs-config
+          mountPath: "/etc/idmapd.conf"
+          subPath: idmapd.conf
+        {{- end }}
         {{- if and .Values.gerritReplica.plugins.cache.enabled .Values.gerritReplica.plugins.downloaded }}
         - name: gerrit-plugin-cache
           mountPath: "/var/mnt/plugins"
@@ -189,6 +199,11 @@
         persistentVolumeClaim:
           claimName: {{ .Release.Name }}-plugin-cache-pvc
       {{- end }}
+      {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+      - name: nfs-config
+        configMap:
+          name: {{ .Release.Name }}-nfs-configmap
+      {{- end }}
       - name: gerrit-init-config
         configMap:
           name: {{ .Release.Name }}-gerrit-init-configmap
diff --git a/helm-charts/gerrit-replica/templates/git-backend.deployment.yaml b/helm-charts/gerrit-replica/templates/git-backend.deployment.yaml
index 867d029..e683d53 100644
--- a/helm-charts/gerrit-replica/templates/git-backend.deployment.yaml
+++ b/helm-charts/gerrit-replica/templates/git-backend.deployment.yaml
@@ -53,6 +53,11 @@
         volumeMounts:
         - name: git-filesystem
           mountPath: "/var/gerrit/git"
+        {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+        - name: nfs-config
+          mountPath: "/etc/idmapd.conf"
+          subPath: idmapd.conf
+        {{- end }}
         - name: git-backend-secret
           readOnly: true
           subPath: .htpasswd
@@ -96,3 +101,8 @@
         {{ else -}}
         emptyDir: {}
         {{- end }}
+      {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+      - name: nfs-config
+        configMap:
+          name: {{ .Release.Name }}-nfs-configmap
+      {{- end }}
diff --git a/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml b/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
index 1ea6981..93832f1 100644
--- a/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
+++ b/helm-charts/gerrit-replica/templates/git-repositories-init.job.yaml
@@ -21,6 +21,23 @@
       imagePullSecrets:
       - name: {{ .Values.images.registry.ImagePullSecret.name }}
       {{- end }}
+      {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+      initContainers:
+      - name: nfs-init
+        image: busybox
+        command:
+        - sh
+        - -c
+        args:
+        - |
+          chown -R 1000:100 /var/mnt/git
+        volumeMounts:
+        - name: git-filesystem
+          mountPath: "/var/mnt/git"
+        - name: nfs-config
+          mountPath: "/etc/idmapd.conf"
+          subPath: idmapd.conf
+      {{- end }}
       containers:
       - name: create-repositories
         image: {{ template "registry" . }}{{ .Values.gerritReplica.images.gerritInit }}:{{ .Values.images.version }}
@@ -70,4 +87,9 @@
       - name: gerrit-config
         configMap:
           name: {{ .Release.Name }}-gerrit-replica-configmap
+      {{- if .Values.gitRepositoryStorage.nfs.enabled }}
+      - name: nfs-config
+        configMap:
+          name: {{ .Release.Name }}-nfs-configmap
+      {{- end }}
       restartPolicy: Never
diff --git a/helm-charts/gerrit-replica/templates/nfs.configmap.yaml b/helm-charts/gerrit-replica/templates/nfs.configmap.yaml
new file mode 100644
index 0000000..ccd7de9
--- /dev/null
+++ b/helm-charts/gerrit-replica/templates/nfs.configmap.yaml
@@ -0,0 +1,24 @@
+{{- if .Values.gitRepositoryStorage.nfs.enabled -}}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Release.Name }}-nfs-configmap
+  labels:
+    app: gerrit-replica
+    chart: {{ template "gerrit-replica.chart" . }}
+    heritage: {{ .Release.Service }}
+    release: {{ .Release.Name }}
+data:
+  idmapd.conf: |-
+    [General]
+
+    Verbosity = 0
+    Pipefs-Directory = /run/rpc_pipefs
+    # set your own domain here, if it differs from FQDN minus hostname
+    Domain = {{ .Values.gitRepositoryStorage.nfs.idDomain }}
+
+    [Mapping]
+
+    Nobody-User = nobody
+    Nobody-Group = nogroup
+{{- end }}
diff --git a/helm-charts/gerrit-replica/values.yaml b/helm-charts/gerrit-replica/values.yaml
index 020bf1d..1d2abae 100644
--- a/helm-charts/gerrit-replica/values.yaml
+++ b/helm-charts/gerrit-replica/values.yaml
@@ -47,6 +47,9 @@
     use: false
     name: git-filesystem-pvc
   size: 5Gi
+  nfs:
+    enabled: false
+    idDomain: localdomain.com
 
 
 istio: