Add pull-replication plugin in `dual-primary` topology. The `replication` plugin (push-replication) is enabled. Note: This change adds the pull-replication plugin when multisite is disabled. The reason is because we want to provide a solution for one site first and after that scale to the multisite topology. Bug: Issue 16393 Change-Id: I8a34525f18cab66ba9c6442e52f84f54f1b4cf70
diff --git a/Secrets.md b/Secrets.md index 16e9711..f0c5c22 100644 --- a/Secrets.md +++ b/Secrets.md
@@ -93,3 +93,12 @@ * replication_user_id_rsa * replication_user_id_rsa.pub + +### Pull-Replication Bearer Token Authentication + +*Optional*. This is only needed if you are setting up a recipe that requires replication +(i.e. primary-replica or dual-primary) + +```bash +openssl rand -hex 20 > /tmp/secrets/pull_replication_bearer_token +```
diff --git a/dual-primary/Makefile b/dual-primary/Makefile index af51604..da22337 100644 --- a/dual-primary/Makefile +++ b/dual-primary/Makefile
@@ -14,8 +14,8 @@ SINGLE_SITE_PLUGINS=javamelody high-availability healthcheck metrics-reporter-cloudwatch -HA_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) aws-dynamodb-refdb -HA_SITE_PLUGINS_LIBS_LINKS=high-availability +HA_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) aws-dynamodb-refdb pull-replication +HA_SITE_PLUGINS_LIBS_LINKS=high-availability pull-replication HA_SITE_MAVEN_LIBS=global-refdb~$(GLOBALREFDB_LIB_VER) MULTI_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) multi-site events-kafka websession-broker aws-dynamodb-refdb @@ -135,6 +135,7 @@ ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY1_SUBDOMAIN) \ ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY1_SUBDOMAIN) \ ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \ + ParameterKey=HttpReplicaSubdomain,ParameterValue=$(HTTP_REPLICA_SUBDOMAIN) \ ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \ ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \ ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\ @@ -197,6 +198,7 @@ ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY2_SUBDOMAIN) \ ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY2_SUBDOMAIN) \ ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \ + ParameterKey=HttpReplicaSubdomain,ParameterValue=$(HTTP_REPLICA_SUBDOMAIN) \ ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \ ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \ ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\ @@ -275,6 +277,8 @@ ParameterKey=GerritCPU,ParameterValue=$(GERRIT_CPU) \ ParameterKey=GerritHeapLimit,ParameterValue=$(GERRIT_HEAP_LIMIT) \ ParameterKey=JgitCacheSize,ParameterValue=$(JGIT_CACHE_SIZE) \ + ParameterKey=HttpPrimariesGerritSubdomain,ParameterValue=$(HTTP_PRIMARIES_GERRIT_SUBDOMAIN) \ + ParameterKey=GerritPrimaryInstanceId,ParameterValue=$(GERRIT_PRIMARY_INSTANCE_ID) $(JGIT_OPTIONAL_PARAMS) \ $(LDAP_ACCOUNT_PATTERN_PARAM) \ $(REPLICA_SERVICE_OPTIONAL_PARAMS) \
diff --git a/dual-primary/cf-service-primary.yml b/dual-primary/cf-service-primary.yml index 0424ab7..f2013f0 100644 --- a/dual-primary/cf-service-primary.yml +++ b/dual-primary/cf-service-primary.yml
@@ -40,6 +40,9 @@ SshReplicaSubdomain: Description: The subdomain of the loadbalancer serving SSH traffic to the replicas Type: String + HttpReplicaSubdomain: + Description: The subdomain of the loadbalancer serving HTTP traffic to the replicas + Type: String HttpPrimariesGerritSubdomain: Description: The subdomain of the load balancer serving HTTP traffic to both gerrit-1 and gerrit-2 Type: String @@ -337,6 +340,8 @@ Value: !FindInMap ['Git', 'SSH', 'Port'] - Name: REPLICA_SUBDOMAIN Value: !Ref SshReplicaSubdomain + - Name: HTTP_REPLICA_SUBDOMAIN + Value: !Ref HttpReplicaSubdomain - Name: GERRIT_INSTANCE_ID Value: !Ref InstanceId - Name: METRICS_CLOUDWATCH_ENABLED
diff --git a/dual-primary/cf-service-replica.yml b/dual-primary/cf-service-replica.yml index 352aa98..6ad486a 100644 --- a/dual-primary/cf-service-replica.yml +++ b/dual-primary/cf-service-replica.yml
@@ -218,7 +218,12 @@ Type: String Default: false AllowedValues: [true, false] - + HttpPrimariesGerritSubdomain: + Description: The subdomain of the loadbalancer serving HTTP traffic to the primaries + Type: String + GerritPrimaryInstanceId: + Description: Gerrit InstanceId shared for all primaries in the same HA + Type: String Mappings: XRay: Info: @@ -288,6 +293,8 @@ Value: !Sub 'proxy-https://*:${HTTPContainePort}/' - Name: CONTAINER_REPLICA Value: true + - Name: SETUP_REPLICATION + Value: true - Name: GERRIT_KEY_PREFIX Value: !Ref GerritKeyPrefix - Name: AWS_REGION @@ -324,6 +331,12 @@ Value: !Ref MetricsCloudwatchDryRun - Name: METRICS_CLOUDWATCH_EXCLUDE_METRICS_LIST Value: !Join [',', !Ref MetricsCloudwatchExcludeMetrics] + - Name: HOSTED_ZONE_NAME + Value: !Ref HostedZoneName + - Name: HTTP_PRIMARIES_GERRIT_SUBDOMAIN + Value: !Ref HttpPrimariesGerritSubdomain + - Name: GERRIT_PRIMARY_INSTANCE_ID + Value: !Ref GerritPrimaryInstanceId Ulimits: - Name: nofile HardLimit: !Ref FileDescriptorsHardLimit
diff --git a/gerrit/add_secrets_aws_secrets_manager.sh b/gerrit/add_secrets_aws_secrets_manager.sh index 2b4fa4e..5b0286a 100755 --- a/gerrit/add_secrets_aws_secrets_manager.sh +++ b/gerrit/add_secrets_aws_secrets_manager.sh
@@ -76,3 +76,8 @@ echo "Adding Prometheus bearer token..." set-secret-string prometheus_bearer_token fi + +if [ -f "$SECRETS_DIRECTORY/pull_replication_bearer_token" ]; then + echo "Adding Pull-Replication Bearer Token..." + set-secret-string pull_replication_bearer_token +fi
diff --git a/gerrit/etc/replication.config.template b/gerrit/etc/replication.config.template index dadc203..c58b73d 100644 --- a/gerrit/etc/replication.config.template +++ b/gerrit/etc/replication.config.template
@@ -17,6 +17,19 @@ replicateHiddenProjects = true timeout = 60 +[remote "replica-1-pull"] + # Issue 16694: pull-replication: Do not force configuration of `url` in remotes + url = {{ REPLICA_1_URL }} + apiUrl = {{ REPLICA_1_API_URL }} + # Issue 16635: pull-replication should provide `mirror` configuration + mirror = true + # Issue 16577: pull-replication: Do not force configuration of `fetch` in remotes + fetch = +refs/*:refs/* + threads = 10 + createMissingRepositories = true + replicateProjectDeletions = true + replicateHiddenProjects = true + timeout = 60 {% if REMOTE_TARGET %} [remote "{{REMOTE_TARGET_URL}}"]
diff --git a/gerrit/etc/replication_replica.config.template b/gerrit/etc/replication_replica.config.template new file mode 100644 index 0000000..59541cd --- /dev/null +++ b/gerrit/etc/replication_replica.config.template
@@ -0,0 +1,19 @@ +[replication] + lockErrorMaxRetries = 30 + maxRetries = 30 + +[gerrit] + autoReload = true + replicateOnStartup = true + +[remote "{{GERRIT_PRIMARY_INSTANCE_ID}}"] + url = {{ HTTP_PRIMARIES_LB }} + # Issue 16635: pull-replication should provide `mirror` configuration + mirror = true + fetch = +refs/*:refs/* + threads = 10 + createMissingRepositories = true + replicateProjectDeletions = true + replicateHiddenProjects = true + timeout = 60 + tagopt= --no-tags \ No newline at end of file
diff --git a/gerrit/setup_gerrit.py b/gerrit/setup_gerrit.py index b181698..de3e439 100755 --- a/gerrit/setup_gerrit.py +++ b/gerrit/setup_gerrit.py
@@ -95,6 +95,8 @@ with open(GERRIT_CONFIG_DIRECTORY + secretId, 'w', encoding='utf-8') as f: f.write(get_secret(GERRIT_KEY_PREFIX + "_" + secretId)) +print("Setup replication: " + str(setupReplication)) + if setupReplication: GERRIT_SSH_DIRECTORY = "/var/gerrit/.ssh" GERRIT_REPLICATION_SSH_KEYS = GERRIT_SSH_DIRECTORY + "/id_rsa" @@ -178,27 +180,45 @@ }) f.write(template.render(config_for_template)) -containerReplica = (os.getenv('CONTAINER_REPLICA') == 'true') -if ((not containerReplica) and setupReplication): - print("Setting Replication config in '" + - GERRIT_CONFIG_DIRECTORY + "replication.config'") - template = env.get_template("replication.config.template") - with open(GERRIT_CONFIG_DIRECTORY + "replication.config", 'w', encoding='utf-8') as f: - REPLICA_FQDN = os.getenv('REPLICA_SUBDOMAIN') + "." + os.getenv('HOSTED_ZONE_NAME') - REMOTE_TARGET = os.getenv('REMOTE_REPLICATION_TARGET_HOST', '') - # In a multi-site setup, the very first replication needs to be - # triggered manually from site-A to site-B, once the latter is ready, - # thus "REPLICATE_ON_STARTUP" needs to be disabled - REPLICATE_ON_STARTUP = "false" if setupMultiSite else "true" - f.write(template.render( - REPLICA_1_URL="git://" + REPLICA_FQDN + ":" + os.getenv('GIT_PORT') + "/${name}.git", - REPLICA_1_AMDIN_URL="ssh://gerrit@" + REPLICA_FQDN + ":" + os.getenv('GIT_SSH_PORT') + "/var/gerrit/git/${name}.git", - REMOTE_TARGET=REMOTE_TARGET, - 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", - REPLICATE_ON_STARTUP=REPLICATE_ON_STARTUP, - MULTISITE_GLOBAL_PROJECTS=os.getenv('MULTISITE_GLOBAL_PROJECTS', '') - )) +if setupReplication: + set_secure_password( + "auth.bearerToken", + get_secret(GERRIT_KEY_PREFIX + "_pull_replication_bearer_token") + ) + containerReplica = (os.getenv('CONTAINER_REPLICA') == 'true') + replication_config_path = GERRIT_CONFIG_DIRECTORY + "replication.config" + + print("Is replica: " + str(containerReplica)) + if containerReplica: + print("Setting replica Replication config in " + str(replication_config_path)) + template = env.get_template("replication_replica.config.template") + with open(replication_config_path, 'w', encoding='utf-8') as f: + PRIMARIES_FQDN = os.getenv('HTTP_PRIMARIES_GERRIT_SUBDOMAIN') + "." + os.getenv('HOSTED_ZONE_NAME') + f.write(template.render( + GERRIT_PRIMARY_INSTANCE_ID=os.getenv('GERRIT_PRIMARY_INSTANCE_ID'), + HTTP_PRIMARIES_LB="https://" + PRIMARIES_FQDN + "/${name}" + )) + else: + print("Setting primary Replication config in " + str(replication_config_path)) + template = env.get_template("replication.config.template") + with open(replication_config_path, 'w', encoding='utf-8') as f: + REPLICA_FQDN = os.getenv('REPLICA_SUBDOMAIN') + "." + os.getenv('HOSTED_ZONE_NAME') + HTTP_REPLICA_FQDN = os.getenv('HTTP_REPLICA_SUBDOMAIN') + "." + os.getenv('HOSTED_ZONE_NAME') + REMOTE_TARGET = os.getenv('REMOTE_REPLICATION_TARGET_HOST', '') + # In a multi-site setup, the very first replication needs to be + # triggered manually from site-A to site-B, once the latter is ready, + # thus "REPLICATE_ON_STARTUP" needs to be disabled + REPLICATE_ON_STARTUP = "false" if setupMultiSite else "true" + f.write(template.render( + REPLICA_1_URL="git://" + REPLICA_FQDN + ":" + os.getenv('GIT_PORT') + "/${name}.git", + REPLICA_1_AMDIN_URL="ssh://gerrit@" + REPLICA_FQDN + ":" + os.getenv('GIT_SSH_PORT') + "/var/gerrit/git/${name}.git", + REPLICA_1_API_URL="https://" + HTTP_REPLICA_FQDN, + REMOTE_TARGET=REMOTE_TARGET, + 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", + REPLICATE_ON_STARTUP=REPLICATE_ON_STARTUP, + MULTISITE_GLOBAL_PROJECTS=os.getenv('MULTISITE_GLOBAL_PROJECTS', '') + )) CONFIGURATION_FILE = "jgit.config" CONFIGURATION_TARGET = GERRIT_CONFIG_DIRECTORY + CONFIGURATION_FILE