Allow gerrit master to replicate to a specified target

Feature: Issue 13287
Change-Id: I446b91a8148ff1e1c9f7b44e8c1256486a4d19d4
diff --git a/dual-master/Makefile b/dual-master/Makefile
index 7a8a325..1b9e80d 100644
--- a/dual-master/Makefile
+++ b/dual-master/Makefile
@@ -65,6 +65,9 @@
 ifdef LDAP_ACCOUNT_PATTERN
 		$(eval MASTER1_SERVICE_OPTIONAL_PARAMS := $(MASTER1_SERVICE_OPTIONAL_PARAMS) ParameterKey=LDAPAccountPattern,ParameterValue=\"$(LDAP_ACCOUNT_PATTERN)\")
 endif
+ifdef REMOTE_REPLICATION_TARGET_HOST
+		$(eval REMOTE_OPTIONAL_PARAMS := $(REMOTE_OPTIONAL_PARAMS) ParameterKey=RemoteReplicationTargetHost,ParameterValue=$(REMOTE_REPLICATION_TARGET_HOST))
+endif
 
 	$(AWS_FC_COMMAND) create-stack \
 		--stack-name $(SERVICE_MASTER1_STACK_NAME) \
@@ -102,6 +105,7 @@
 		ParameterKey=GerritCPU,ParameterValue=$(GERRIT_CPU) \
 		ParameterKey=GerritHeapLimit,ParameterValue=$(GERRIT_HEAP_LIMIT) \
 		ParameterKey=JgitCacheSize,ParameterValue=$(JGIT_CACHE_SIZE) \
+		$(REMOTE_OPTIONAL_PARAMS) \
 		$(MASTER1_SERVICE_OPTIONAL_PARAMS) \
 		$(METRICS_CW_OPTIONAL_PARAMS) \
 		$(SMTP_OPTIONAL_PARAMS)
@@ -113,6 +117,9 @@
 ifdef LDAP_ACCOUNT_PATTERN
 		$(eval MASTER2_SERVICE_OPTIONAL_PARAMS := $(MASTER2_SERVICE_OPTIONAL_PARAMS) ParameterKey=LDAPAccountPattern,ParameterValue=\"$(LDAP_ACCOUNT_PATTERN)\")
 endif
+ifdef REMOTE_REPLICATION_TARGET_HOST
+		$(eval REMOTE_OPTIONAL_PARAMS := $(REMOTE_OPTIONAL_PARAMS) ParameterKey=RemoteReplicationTargetHost,ParameterValue=$(REMOTE_REPLICATION_TARGET_HOST))
+endif
 
 	$(AWS_FC_COMMAND) create-stack \
 		--stack-name $(SERVICE_MASTER2_STACK_NAME) \
@@ -151,6 +158,7 @@
 		ParameterKey=GerritCPU,ParameterValue=$(GERRIT_CPU) \
 		ParameterKey=GerritHeapLimit,ParameterValue=$(GERRIT_HEAP_LIMIT) \
 		ParameterKey=JgitCacheSize,ParameterValue=$(JGIT_CACHE_SIZE) \
+		$(REMOTE_OPTIONAL_PARAMS) \
 		$(MASTER2_SERVICE_OPTIONAL_PARAMS) \
 		$(METRICS_CW_OPTIONAL_PARAMS) \
 		$(SMTP_OPTIONAL_PARAMS)
diff --git a/dual-master/README.md b/dual-master/README.md
index 3e592d0..ce7e1de 100644
--- a/dual-master/README.md
+++ b/dual-master/README.md
@@ -117,6 +117,17 @@
 * `GIT_REPLICATION_SUBDOMAIN`: Optional. The subdomain to use for the replication endpoint.
 "git-replication" by default.
 
+It is also posssible to replicate *to* an extra target by providing a FQDN.
+The target is expected to expose port 9148 and port 1022 for git and git admin
+operations respectively.
+
+* `REMOTE_REPLICATION_TARGET_HOST`: Optional.  The fully qualified domain name of a remote replication target.
+Empty by default.
+
+The replication service and the remote replication target represent the reading
+and writing sides of Git replication: by enabling both of them, it is possible to
+establish replication to a remote Git site.
+
 ### 2 - Deploy
 
 * Create the cluster, services and DNS routing stacks:
diff --git a/dual-master/cf-service-master.yml b/dual-master/cf-service-master.yml
index 5605d8d..9ea8238 100644
--- a/dual-master/cf-service-master.yml
+++ b/dual-master/cf-service-master.yml
@@ -213,6 +213,10 @@
     Description: Comma separated list of regex patterns to exclude metrics reported to CloudWatch
     Type: CommaDelimitedList
     Default: ''
+  RemoteReplicationTargetHost:
+    Description: The fully qualified domain name of a remote replication target
+    Type: String
+    Default: ''
 
 Resources:
     Service:
@@ -312,6 +316,8 @@
                       Value: !Ref MetricsCloudwatchDryRun
                     - Name: METRICS_CLOUDWATCH_EXCLUDE_METRICS_LIST
                       Value: !Join [',', !Ref MetricsCloudwatchExcludeMetrics]
+                    - Name: REMOTE_REPLICATION_TARGET_HOST
+                      Value: !Ref RemoteReplicationTargetHost
                   MountPoints:
                     - SourceVolume: !Ref GerritGitVolume
                       ContainerPath: /var/gerrit/git
diff --git a/dual-master/setup.env.template b/dual-master/setup.env.template
index e4a6c2b..5b646d1 100644
--- a/dual-master/setup.env.template
+++ b/dual-master/setup.env.template
@@ -7,6 +7,7 @@
 SERVICE_REPLICATION_STACK_NAME:=$(AWS_PREFIX)-service-replication
 SERVICE_REPLICATION_DESIRED_COUNT:=1
 GIT_REPLICATION_SUBDOMAIN:=$(AWS_PREFIX)-replication
+# REMOTE_REPLICATION_TARGET_HOST:=other-site-replication.yourcompany.com
 
 SERVICE_SLAVE_STACK_NAME:=$(AWS_PREFIX)-service-slave
 HTTP_HOST_PORT_MASTER2:=8081
diff --git a/gerrit/etc/replication.config.template b/gerrit/etc/replication.config.template
index 814a4a9..4f22f1b 100644
--- a/gerrit/etc/replication.config.template
+++ b/gerrit/etc/replication.config.template
@@ -18,3 +18,17 @@
   replicateProjectDeletions = true
   replicateHiddenProjects = true
   timeout = 60
+
+
+{% if REMOTE_TARGET_URL %}
+[remote "{{REMOTE_TARGET_URL}}"]
+  url = {{ REMOTE_TARGET_URL }}
+  adminUrl = {{ REMOTE_ADMIN_TARGET_URL }}
+  mirror = true
+  push = +refs/*:refs/*
+  threads = 10
+  createMissingRepositories = true
+  replicateProjectDeletions = true
+  replicateHiddenProjects = true
+  timeout = 60
+{% endif %}
\ No newline at end of file
diff --git a/gerrit/setup_gerrit.py b/gerrit/setup_gerrit.py
index 18ce4fd..0a9439c 100755
--- a/gerrit/setup_gerrit.py
+++ b/gerrit/setup_gerrit.py
@@ -168,9 +168,12 @@
     template = env.get_template("replication.config.template")
     with open(GERRIT_CONFIG_DIRECTORY + "replication.config", 'w', encoding='utf-8') as f:
         SLAVE_FQDN = os.getenv('SLAVE_SUBDOMAIN') + "." + os.getenv('HOSTED_ZONE_NAME')
+        REMOTE_TARGET = os.getenv('REMOTE_REPLICATION_TARGET_HOST', '')
         f.write(template.render(
                 SLAVE_1_URL="git://" + SLAVE_FQDN + ":" + os.getenv('GIT_PORT') + "/${name}.git",
-                SLAVE_1_AMDIN_URL="ssh://gerrit@" + SLAVE_FQDN + ":" + os.getenv('GIT_SSH_PORT') + "/var/gerrit/git/${name}.git"
+                SLAVE_1_AMDIN_URL="ssh://gerrit@" + SLAVE_FQDN + ":" + os.getenv('GIT_SSH_PORT') + "/var/gerrit/git/${name}.git",
+                REMOTE_TARGET_URL="git://" + REMOTE_TARGET + ":" + os.getenv('GIT_PORT') + "/${name}.git",
+                REMOTE_ADMIN_TARGET_URL="ssh://gerrit@" + REMOTE_TARGET + ":" + os.getenv('GIT_SSH_PORT') + "/var/gerrit/git/${name}.git",
                 ))
 
 if (setupHA):