Add ssh_server option to Gerrit driver

In a multi-host Gerrit environment (HA or failover) it's plausible
that admins may use one mechanism for managing ingress for HTTP
requests and a different for SSH requests.  Or admins may have
different firewall rules for each. To accomodate these situations,
Add an "ssh_server" configuration item for Gerrit.  This makes the
set of hostname-like items the following:

* server: the HTTP hostname and default for all others
* canonical_hostname: what to use for golang-style git paths
* ssh_server: the hostname to use for SSH connections
* baseurl: the base URL for HTTP connections

The following are equivalent:
  server=review.example.com
  ssh_server=ssh-review.example.com
and:
  server=ssh-review.example.com
  baseurl=https://review.example.com

Change-Id: I6e9cd9f48c1a78d8d24bfe176efbb932a18ec83c
This commit is contained in:
James E. Blair 2022-06-17 14:10:07 -07:00
parent c5b55e59c8
commit 595fb3e9ef
6 changed files with 77 additions and 4 deletions

View File

@ -51,6 +51,12 @@ The supported options in ``zuul.conf`` connections are:
Fully qualified domain name of Gerrit server.
.. attr:: ssh_server
If SSH access to the Gerrit server should be via a different
hostname than web access, set this value to the hostname to use
for SSH connections.
.. attr:: canonical_hostname
The canonical hostname associated with the git repos on the

View File

@ -0,0 +1,6 @@
---
features:
- |
The new `ssh_server` option for gerrit connections may be used to specify
a hostname to use for SSH connections while the normal `server` option
specifies the hostname to use for HTTP connections.

38
tests/fixtures/zuul-gerrit-ssh.conf vendored Normal file
View File

@ -0,0 +1,38 @@
[statsd]
# note, use 127.0.0.1 rather than localhost to avoid getting ipv6
# see: https://github.com/jsocol/pystatsd/issues/61
server=127.0.0.1
[scheduler]
tenant_config=main.yaml
[merger]
git_dir=/tmp/zuul-test/merger-git
git_user_email=zuul@example.com
git_user_name=zuul
[executor]
git_dir=/tmp/zuul-test/executor-git
load_multiplier=100
[connection gerrit]
driver=gerrit
server=review.example.com
ssh_server=ssh-review.example.com
user=jenkins
sshkey=fake_id_rsa_path
password=badpassword
[connection github]
driver=github
webhook_token=0000000000000000000000000000000000000000
[connection smtp]
driver=smtp
server=localhost
port=25
default_from=zuul@example.com
default_to=you@example.com
[database]
dburi=$MYSQL_FIXTURE_DBURI$

View File

@ -148,6 +148,25 @@ class TestGerrit(BaseTestCase):
'ssh://gerrit@localhost:29418/org/project',
url)
def test_ssh_server_getGitURL(self):
gerrit_config = {
'user': 'gerrit',
'server': 'otherserver',
'password': '1/badpassword',
'ssh_server': 'localhost',
'git_over_ssh': 'true',
}
# The 1/ in the password ensures we test the url encoding
# path; this is the format of password we get from
# googlesource.com.
driver = GerritDriver()
gerrit = GerritConnection(driver, 'review_gerrit', gerrit_config)
project = gerrit.source.getProject('org/project')
url = gerrit.source.getGitUrl(project)
self.assertEqual(
'ssh://gerrit@localhost:29418/org/project',
url)
class TestGerritWeb(ZuulTestCase):
config_file = 'zuul-gerrit-web.conf'

View File

@ -316,6 +316,7 @@ class TestWeb(BaseTestWeb):
'baseurl': 'https://review.example.com',
'canonical_hostname': 'review.example.com',
'server': 'review.example.com',
'ssh_server': 'review.example.com',
'port': 29418,
}
self.assertEqual([connection], data)
@ -2954,7 +2955,7 @@ class TestHeldAttributeInBuildInfo(BaseTestWeb):
class TestWebMulti(BaseTestWeb):
config_file = 'zuul-gerrit-github.conf'
config_file = 'zuul-gerrit-ssh.conf'
def test_web_connections_list_multi(self):
data = self.get_url('api/connections').json()
@ -2966,6 +2967,7 @@ class TestWebMulti(BaseTestWeb):
'baseurl': url,
'canonical_hostname': 'review.example.com',
'server': 'review.example.com',
'ssh_server': 'ssh-review.example.com',
'port': 29418,
}
github_connection = {

View File

@ -578,6 +578,7 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
self.user = self.connection_config.get('user')
self.server = self.connection_config.get('server')
self.ssh_server = self.connection_config.get('ssh_server', self.server)
self.canonical_hostname = self.connection_config.get(
'canonical_hostname', self.server)
self.port = int(self.connection_config.get('port', 29418))
@ -680,6 +681,7 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
"baseurl": self.baseurl,
"canonical_hostname": self.canonical_hostname,
"server": self.server,
"ssh_server": self.ssh_server,
"port": self.port,
})
return d
@ -1535,7 +1537,7 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
client.set_missing_host_key_policy(paramiko.WarningPolicy())
# SSH banner, handshake, and auth timeouts default to 15
# seconds, so we only set the socket timeout here.
client.connect(self.server,
client.connect(self.ssh_server,
username=self.user,
port=self.port,
key_filename=self.keyfile,
@ -1626,7 +1628,7 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
baseurl = urllib.parse.urlunparse(baseurl)
url = ('%s/a/%s' % (baseurl, project.name))
else:
url = 'ssh://%s@%s:%s/%s' % (self.user, self.server, self.port,
url = 'ssh://%s@%s:%s/%s' % (self.user, self.ssh_server, self.port,
project.name)
return url
@ -1717,7 +1719,7 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
self.watcher_thread = GerritWatcher(
self,
self.user,
self.server,
self.ssh_server,
self.port,
keyfile=self.keyfile,
keepalive=self.keepalive)