Merge "Add some debug entries to executor" into feature/zuulv3
diff --git a/.gitignore b/.gitignore
index d6a7477..a2dd0a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,9 +7,12 @@
 .testrepository
 .tox
 .venv
+.coverage
 AUTHORS
 build/*
 ChangeLog
 doc/build/*
 zuul/versioninfo
 dist/
+cover/
+htmlcov/
diff --git a/doc/source/zuul.rst b/doc/source/zuul.rst
index a7dfb44..a2a6918 100644
--- a/doc/source/zuul.rst
+++ b/doc/source/zuul.rst
@@ -52,6 +52,16 @@
   Port on which the Gearman server is listening.
   ``port=4730`` (optional)
 
+**ssl_ca**
+  Optional: An openssl file containing a set of concatenated “certification authority” certificates
+  in PEM formet.
+
+**ssl_cert**
+  Optional: An openssl file containing the client public certificate in PEM format.
+
+**ssl_key**
+  Optional: An openssl file containing the client private key in PEM format.
+
 gearman_server
 """"""""""""""
 
@@ -70,6 +80,16 @@
   Path to log config file for internal Gearman server.
   ``log_config=/etc/zuul/gearman-logging.yaml``
 
+**ssl_ca**
+  Optional: An openssl file containing a set of concatenated “certification authority” certificates
+  in PEM formet.
+
+**ssl_cert**
+  Optional: An openssl file containing the server public certificate in PEM format.
+
+**ssl_key**
+  Optional: An openssl file containing the server private key in PEM format.
+
 webapp
 """"""
 
diff --git a/etc/zuul.conf-sample b/etc/zuul.conf-sample
index 1065cec..1aee1fa 100644
--- a/etc/zuul.conf-sample
+++ b/etc/zuul.conf-sample
@@ -1,8 +1,14 @@
 [gearman]
 server=127.0.0.1
+;ssl_ca=/path/to/ca.pem
+;ssl_cert=/path/to/client.pem
+;ssl_key=/path/to/client.key
 
 [gearman_server]
 start=true
+;ssl_ca=/path/to/ca.pem
+;ssl_cert=/path/to/server.pem
+;ssl_key=/path/to/server.key
 
 [zuul]
 layout_config=/etc/zuul/layout.yaml
diff --git a/tests/base.py b/tests/base.py
index 7d33ffc..31d6f0d 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -1356,9 +1356,20 @@
 
     """
 
-    def __init__(self):
+    def __init__(self, use_ssl=False):
         self.hold_jobs_in_queue = False
-        super(FakeGearmanServer, self).__init__(0)
+        if use_ssl:
+            ssl_ca = os.path.join(FIXTURE_DIR, 'gearman/root-ca.pem')
+            ssl_cert = os.path.join(FIXTURE_DIR, 'gearman/server.pem')
+            ssl_key = os.path.join(FIXTURE_DIR, 'gearman/server.key')
+        else:
+            ssl_ca = None
+            ssl_cert = None
+            ssl_key = None
+
+        super(FakeGearmanServer, self).__init__(0, ssl_key=ssl_key,
+                                                ssl_cert=ssl_cert,
+                                                ssl_ca=ssl_ca)
 
     def getJobForConnection(self, connection, peek=False):
         for queue in [self.high_queue, self.normal_queue, self.low_queue]:
@@ -1812,6 +1823,7 @@
     config_file = 'zuul.conf'
     run_ansible = False
     create_project_keys = False
+    use_ssl = False
 
     def _startMerger(self):
         self.merge_server = zuul.merger.server.MergeServer(self.config,
@@ -1869,11 +1881,22 @@
         reload_module(statsd)
         reload_module(zuul.scheduler)
 
-        self.gearman_server = FakeGearmanServer()
+        self.gearman_server = FakeGearmanServer(self.use_ssl)
 
         self.config.set('gearman', 'port', str(self.gearman_server.port))
         self.log.info("Gearman server on port %s" %
                       (self.gearman_server.port,))
+        if self.use_ssl:
+            self.log.info('SSL enabled for gearman')
+            self.config.set(
+                'gearman', 'ssl_ca',
+                os.path.join(FIXTURE_DIR, 'gearman/root-ca.pem'))
+            self.config.set(
+                'gearman', 'ssl_cert',
+                os.path.join(FIXTURE_DIR, 'gearman/client.pem'))
+            self.config.set(
+                'gearman', 'ssl_key',
+                os.path.join(FIXTURE_DIR, 'gearman/client.key'))
 
         gerritsource.GerritSource.replication_timeout = 1.5
         gerritsource.GerritSource.replication_retry_interval = 0.5
@@ -2683,6 +2706,11 @@
     run_ansible = True
 
 
+class SSLZuulTestCase(ZuulTestCase):
+    """ZuulTestCase but using SSL when possible"""
+    use_ssl = True
+
+
 class ZuulDBTestCase(ZuulTestCase):
     def setup_config(self):
         super(ZuulDBTestCase, self).setup_config()
diff --git a/tests/fixtures/gearman/README.rst b/tests/fixtures/gearman/README.rst
new file mode 100644
index 0000000..a3921ea
--- /dev/null
+++ b/tests/fixtures/gearman/README.rst
@@ -0,0 +1,21 @@
+Steps used to create our certs
+
+# Generate CA cert
+$ openssl req -new -newkey rsa:2048 -nodes -keyout root-ca.key -x509 -days 3650 -out root-ca.pem -subj "/C=US/ST=Texas/L=Austin/O=OpenStack Foundation/CN=gearman-ca"
+
+# Generate server keys
+$ CLIENT='server'
+$ openssl req -new -newkey rsa:2048 -nodes -keyout $CLIENT.key -out $CLIENT.csr -subj "/C=US/ST=Texas/L=Austin/O=OpenStack Foundation/CN=nodepool-$CLIENT"
+$ openssl x509 -req -days 3650 -in $CLIENT.csr -out $CLIENT.pem -CA root-ca.pem -CAkey root-ca.key -CAcreateserial
+
+
+# Generate client keys
+$ CLIENT='client'
+$ openssl req -new -newkey rsa:2048 -nodes -keyout $CLIENT.key -out $CLIENT.csr -subj "/C=US/ST=Texas/L=Austin/O=OpenStack Foundation/CN=gearman-$CLIENT"
+$ openssl x509 -req -days 3650 -in $CLIENT.csr -out $CLIENT.pem -CA root-ca.pem -CAkey root-ca.key -CAcreateserial
+
+
+# Test with geard
+# You'll need 2 terminal windows
+geard --ssl-ca root-ca.pem --ssl-cert server.pem --ssl-key server.key -d
+openssl s_client -connect localhost:4730 -key client.key -cert client.pem -CAfile root-ca.pem
diff --git a/tests/fixtures/gearman/client.csr b/tests/fixtures/gearman/client.csr
new file mode 100644
index 0000000..fadb857
--- /dev/null
+++ b/tests/fixtures/gearman/client.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICqzCCAZMCAQAwZjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYD
+VQQHDAZBdXN0aW4xHTAbBgNVBAoMFE9wZW5TdGFjayBGb3VuZGF0aW9uMRcwFQYD
+VQQDDA5nZWFybWFuLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALe+ByAkac9cYjeV8lcWXhDxdFqb7Om+6cWSJ/hpM4Z5QyGJ9XHDWyhrmt5W
+X2jvE/bAxEWXxWj3v8xR5HbjS6XHBHouQxz+FSDcG1GZjOLK5fwnO5tKG5eLdrAN
+WgOqJynJAsA0IuxURI4LiBUnzdi/10VeygwSIHOBLVWfrTZNKiE8siiQIaUAerLT
+T8BEUEAUI38UhS4OT83QGUbcCPOkioE5/Q8VVpvlu3eIIEkkacs5293EfUvQRVSG
++GYjSHfFBV7ECX7gu/4nosa/bLfQw7F9O1C2E6QEoUqVNEtURXT0ALlGkUylq6H9
+ctVjoJS9iW8ToMtajW2PZVI/d6MCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBc
+v3/Z9Exc7pnbwyL31ZGv+gF0Z1l9CaSobdI3JAMzKxYGK9SxYOAwcwuUL0+zAJEE
+VPAaWM0p6eVF6j0d97Q79XsHvIKvyVYFxZ9rYSI+cvAIxhws1b4YtRoPBlY3AajV
+u2CQDVos/8JB28X3DpM4MJRua2tnTfAGLCkEp1psAoND+rr5eL7j+naUcPvNMv7Z
+WnTbIJYmP/6N+8gGGtAiiibXP3/Z92kFUZZxKNt3YSHfhkGY57/p+d8i3/8B+qeA
+/YfohA4hNLPydcw32kzo7865+h3SMdbX7VF8xB9grbZXvkT26rtrFJxWLOf5Vmzi
+aGPrVyPIeyVJvW3EeJQ9
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/fixtures/gearman/client.key b/tests/fixtures/gearman/client.key
new file mode 100644
index 0000000..656cfc7
--- /dev/null
+++ b/tests/fixtures/gearman/client.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3vgcgJGnPXGI3
+lfJXFl4Q8XRam+zpvunFkif4aTOGeUMhifVxw1soa5reVl9o7xP2wMRFl8Vo97/M
+UeR240ulxwR6LkMc/hUg3BtRmYziyuX8JzubShuXi3awDVoDqicpyQLANCLsVESO
+C4gVJ83Yv9dFXsoMEiBzgS1Vn602TSohPLIokCGlAHqy00/ARFBAFCN/FIUuDk/N
+0BlG3AjzpIqBOf0PFVab5bt3iCBJJGnLOdvdxH1L0EVUhvhmI0h3xQVexAl+4Lv+
+J6LGv2y30MOxfTtQthOkBKFKlTRLVEV09AC5RpFMpauh/XLVY6CUvYlvE6DLWo1t
+j2VSP3ejAgMBAAECggEAF5cAFzJVm1fDDFvl9yRaA1bcl115dzEZllIDa7Ml+FfN
+NJsftfFc3L2j7nOsYC6Bo6ZwDHdF0worx7Gj4VehOLFqc71IxIoicEuR/lH2co+W
+I19uGavUCwrOvB+atOm9iXHTNpX6/dh7zLjSSdUIapGGs9NNoWsaW3n0NhAADv51
+SQYemDgG9/vLGPoouUGTBkMNCuI+uHP1C+nRSs/kikebjVqYoDNPm1/ADpccde9p
+mntezm9v/xDXzVFD2qQTTve1mDpoy6YLZdY0mT6qUNElwZ+yZHXkBox1tpJ69Uw+
+pGanSMOy/Gj3W5RlX4qTSLLRcSePV8x65MzRwFoxgQKBgQDstP1/sfnS3JBWSW6V
+YAN3alXeyb0bH0uA+nfXRzy9GnwlFTAszzwnbKL9xK+hPjJRkDBf8XDyXKQ3FMyi
+OVf+H2IkhwErQL01qG4k8E3Hk9wQMvjdO00SaEiLD2uMxX9lRCs9vVlvtmSbGvTH
+/RXBFnqYDHeMJxnWZ8Y34chtoQKBgQDGt+cYtoXH79imuyOQ1SORtIQtSGEKcIcg
+20o5tCGJfCxLtrKs7n4Yph9IPvMtiA8idPACWU2Q8XV580RABzC7Am8ICGGJSwN8
+PLoWOadEpYYeFOV8Mzfxs/YhdQat6zvGy8sF0O+DER0b1ELfbA1I+FNOuz0y53AJ
+MXxOUvQ2wwKBgAFWHEBGTvTDzgTOsVMikaJw9T8mwGyQxqpZv6d1fYBLz/udnQID
+wYEvedQY8izk3v/a4osIH+0eXMb61RTtYfPLVZCDOpx15xuQcd6/hJDl4s4sm38U
+QKEj+ZTfZ2oKC2gU9HGKyiB5VSQTCOLAKQlICTUmjN47skelmlbibXFBAoGBAIHn
+UoELQGU1W3GTQGq7imcDlKxtdlJ2wT8vW1RhdtMDg4lzQ1ZdCb1fS2/VBu8q1In3
+27YNXvFzhxJTfrhEewylSKP9ppUznnGm2RcSVVBAzG35xxLsAJRWyn2QnO8wqYEJ
+VAzXSttpYpgAqD6Zyg17mCoNqLIQLWM1IEerXs41AoGAGdswRmzQ2oHF0f01yZaq
+rxGtLOuTyHzmwi8vA4qZj/9Baht9ihVJiqxTAg/CuA3sTM7DxAJ6P5h6mHsVM6bh
+tPVruBdPIOg4XchcXory1Pa8wSHsPkEnj2NnrZRhvcv86vFxDkhu601nv+AGHj1D
+szjDKeH4IP8fjbf/utRxo3w=
+-----END PRIVATE KEY-----
diff --git a/tests/fixtures/gearman/client.pem b/tests/fixtures/gearman/client.pem
new file mode 100644
index 0000000..aac9d8d
--- /dev/null
+++ b/tests/fixtures/gearman/client.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRDCCAiwCCQDnKP1tRJr+2DANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJV
+UzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkF1c3RpbjEdMBsGA1UECgwUT3Bl
+blN0YWNrIEZvdW5kYXRpb24xEzARBgNVBAMMCmdlYXJtYW4tY2EwHhcNMTcwNjE0
+MTQwNzAwWhcNMjcwNjEyMTQwNzAwWjBmMQswCQYDVQQGEwJVUzEOMAwGA1UECAwF
+VGV4YXMxDzANBgNVBAcMBkF1c3RpbjEdMBsGA1UECgwUT3BlblN0YWNrIEZvdW5k
+YXRpb24xFzAVBgNVBAMMDmdlYXJtYW4tY2xpZW50MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAt74HICRpz1xiN5XyVxZeEPF0Wpvs6b7pxZIn+GkzhnlD
+IYn1ccNbKGua3lZfaO8T9sDERZfFaPe/zFHkduNLpccEei5DHP4VINwbUZmM4srl
+/Cc7m0obl4t2sA1aA6onKckCwDQi7FREjguIFSfN2L/XRV7KDBIgc4EtVZ+tNk0q
+ITyyKJAhpQB6stNPwERQQBQjfxSFLg5PzdAZRtwI86SKgTn9DxVWm+W7d4ggSSRp
+yznb3cR9S9BFVIb4ZiNId8UFXsQJfuC7/ieixr9st9DDsX07ULYTpAShSpU0S1RF
+dPQAuUaRTKWrof1y1WOglL2JbxOgy1qNbY9lUj93owIDAQABMA0GCSqGSIb3DQEB
+CwUAA4IBAQBSYRP7DDGRBs1wwudH2HzaDRNZrhECUq6n45FY3YHkDU5xxi6CA3wD
+EA+fvvB95BvqNNCS4UxQMW3k7cgJQrUVBKXj9m5HqE/GVZuI15+bR9i7vc5USoen
+nfbVhDAvZcrzPhmj/pfnXKwgeE7PhG55mrJvJgSmxmK2wTcRRIQ6dfoj3OIJJHEY
+kW3oK8I+9r5Tufxbg+CIpZVIuENbRDNGhTPCtzDu3q6DHAEOBKHmwc64W/2c+2QV
+CpfPdutVF2reb6CJuGikM8WMh47mksNIyCW832bUvUCDgW4/tqanPqww4lTdU44b
+W8gkkWcUmOa6MVCXIzCy7tEbkEDJC2NE
+-----END CERTIFICATE-----
diff --git a/tests/fixtures/gearman/root-ca.key b/tests/fixtures/gearman/root-ca.key
new file mode 100644
index 0000000..3db94c3
--- /dev/null
+++ b/tests/fixtures/gearman/root-ca.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAglCCv7aQxXZg
+8wuLq0QuIQbZbK1Y0aFwMaEpOeVyZR/C42nws3hH0BivJZnr5w57fdT2OXFqkAyl
+Pw+sF8PcDlSi2wF33rnswz8qYszX5WUgvGnOtcJx8YJhqBqNCLb0wnneJqNQpXPs
+CmcsEeBMsCVN9Q1cRMgdjyMBpRfcq7WH5NN+o/n4zClHYZwa3wOyH2ipekl4XTEf
+Kz9aq88L3YE/N4dyUWH0UpS+lBem+D0GAarV2IXWqXeMrWce930mBONMhBrgw0X5
+QFrDa0KQn2QRcg9tqlEE9SlAbub/yHUsq7/7q7l6SWl7JBigj4jGw15w98WzSDkJ
+a0we1jexAgMBAAECggEAX/HS3IdeHyM7D7CyZWbzcSYmusBuWOEJ29fwYZKoZ248
++S3MhBl+bhQp6UkNQMSEtEmPlTQl8Z1foBAg6H1jsU43In+SaMLJ2VWqKp7ZRxTe
+ZQVimpJ+GbnraG6W5Qmd3bj7chvBs5TyhIbeytkR+EamIQdsJDtnnUvUf6JflSvl
+gUZxOvfB7UZQZ2PkMQFleZxlEAvgyk8e4k7AnY2IoTyvw1DIUdP7+7hPInBpWaUn
+jJPZzyWyrMDLB+BB7JcdqmO2N5bHudE4iEJwphmdIcHvOFhm/LHfJdZg6+X8lUCP
+lIfzp6Uk25nF5/dsoZQcrdBznhW4NfJsIviui+SSAQKBgQDrVI4pW/1fU4AYoOki
+jB+RaUaBXkRRV6MYJ/ZUPjAONDtFhDdBDEwunVUpTD8sgVKFnaMzNa/+Jcmy4jsE
+Ggj9ZupH05g9Y8w7dYFcfT6VeiPahyml8k/DWWe0qQk0+scH8vuiWcrqIjWRg4WD
+8CXJqSkgrCHFCjuJOvxM24d1UQKBgQDRaupcR/c9AGpUHmhFGexwOyXtIR2ObaVf
+lEZ9rhrpCRAl5RW0tUmd1vHMNDTdRidfYLFe29h6YQ1afgNcV8JdB51VfurJ+cOF
+jbc6FijDag31snIdBnDuV29mazejRm7PSfJjoBnBDNzh3kMed22DsQDlHQmudknH
+wUqUWnWEYQKBgG3bYSoJmXRgxJG6vFq2Ux5MqO9HlFjssmRac3HMPh7DX1AKcsjY
+9s9j/xdyUqNyE5Xwivki/O+FsGzjk21MwhmZa5DwREeUSQkQx7zncsnQ5N/k7Rpc
+zcOB/xmlN3kWAMfDNJkLleBK6/rsDO4Us286msp30KPtLPHZKWKvsMKhAoGAaiER
+5nR+Qsb8G+dRFnv9zB7dqKAYt36vyZF+a+EZODJkoZ/IcU1SopA0+DUY+W69M2Pw
+X89wlQysVMj58Ql0serS/GoWmQdf5EYermxeejI8IuEtXbJO9ysOhMwfZTqjm5+x
+HHYdty1Kn5khUMZblNrWRkaCCo1d9MLrheWWGuECgYEAy5kdeVE8lLliFL39Xrzl
+OCJ1rEIAhXrqr6E3PrMlUiQ75dAOiLEl3GGG7UkSHL/0dZv50RRee+4hxI63P2z0
+xPeH2nvrFzknmabOWxtOpw+H0qGOYto9VcvseFPNKTV2O5wxdfaYgLEOXt8ipaLD
+OVvm6yN1bP1Gxi6vdVppKwk=
+-----END PRIVATE KEY-----
diff --git a/tests/fixtures/gearman/root-ca.pem b/tests/fixtures/gearman/root-ca.pem
new file mode 100644
index 0000000..defedd6
--- /dev/null
+++ b/tests/fixtures/gearman/root-ca.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDlzCCAn+gAwIBAgIJAPmWfgTknq1hMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGluMR0wGwYDVQQK
+DBRPcGVuU3RhY2sgRm91bmRhdGlvbjETMBEGA1UEAwwKZ2Vhcm1hbi1jYTAeFw0x
+NzA2MTQxNDA1NDNaFw0yNzA2MTIxNDA1NDNaMGIxCzAJBgNVBAYTAlVTMQ4wDAYD
+VQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGluMR0wGwYDVQQKDBRPcGVuU3RhY2sg
+Rm91bmRhdGlvbjETMBEGA1UEAwwKZ2Vhcm1hbi1jYTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMCCUIK/tpDFdmDzC4urRC4hBtlsrVjRoXAxoSk55XJl
+H8LjafCzeEfQGK8lmevnDnt91PY5cWqQDKU/D6wXw9wOVKLbAXfeuezDPypizNfl
+ZSC8ac61wnHxgmGoGo0ItvTCed4mo1Clc+wKZywR4EywJU31DVxEyB2PIwGlF9yr
+tYfk036j+fjMKUdhnBrfA7IfaKl6SXhdMR8rP1qrzwvdgT83h3JRYfRSlL6UF6b4
+PQYBqtXYhdapd4ytZx73fSYE40yEGuDDRflAWsNrQpCfZBFyD22qUQT1KUBu5v/I
+dSyrv/uruXpJaXskGKCPiMbDXnD3xbNIOQlrTB7WN7ECAwEAAaNQME4wHQYDVR0O
+BBYEFDIaceZ/LY42aNSV0hisgSEcnjlMMB8GA1UdIwQYMBaAFDIaceZ/LY42aNSV
+0hisgSEcnjlMMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKN60Jnx
+NPSkDlqrKtcojX3+oVPC5MQctysZXmjjkGzHSAVKeonQ+gN/glfRc0qq/PuzvHej
+a2Mk9CirL2VzBgp1d/sGtOijqI0Otn706SBuQl1PEAzcmTyQt7TuhUnVcV22xBwy
+ONIuXVT5eh8MhUdrlqZKXX9U49sjmHCheJFFVqFmy0twlqf9YikC0CNxiWa/jDhj
+bxi73kxgZTb2RPjwYUWbESfyNCq0H+N2BmSz7Fgc2Ah/wvhXGdx1udaDVgzDqFIR
+lMGswkzmd76JpJdN0Rce7lmRoE8E6BqDShvoEGiGo3IbuOUwn5JRKFMUPhN6mv7N
+c49ykHzcCgc1wdY=
+-----END CERTIFICATE-----
diff --git a/tests/fixtures/gearman/root-ca.srl b/tests/fixtures/gearman/root-ca.srl
new file mode 100644
index 0000000..0ce584a
--- /dev/null
+++ b/tests/fixtures/gearman/root-ca.srl
@@ -0,0 +1 @@
+E728FD6D449AFED8
diff --git a/tests/fixtures/gearman/server.csr b/tests/fixtures/gearman/server.csr
new file mode 100644
index 0000000..bbb03d2
--- /dev/null
+++ b/tests/fixtures/gearman/server.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICrDCCAZQCAQAwZzELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYD
+VQQHDAZBdXN0aW4xHTAbBgNVBAoMFE9wZW5TdGFjayBGb3VuZGF0aW9uMRgwFgYD
+VQQDDA9ub2RlcG9vbC1zZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCzoKkaauTNBRry1Y5YCNG38IrxW0AH5TP5XdTF/q+Qu1p9onRsACiSZX8Y
+YAo/y6jVbZ3WKihVfVIQw9xrPTCoA0AwMtI8fiK70YwSuGg6gqBBCr8NXOaYsYFJ
+k2Vk+8utlNSmLYlcSTKZR0HbhWNmjH9lj5WngL0XPSbcoogtvet92111qGfBZrg+
+86B3XJh2/6PCru9YmufqlooFog7Q4Qo6Bnz7Dh+h2QjtDmGSFz0dQ9PqP8Jgh3LS
+fWRk5TrjGsthKszRTZCQDSXc1XcwAqfO21eufP9oTpfc0zTdAOC1tspdP/632q6B
+0Gf8sSEnMpKmwuGUH3z2ZCY6DSE1AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEA
+NPZ0BNt9vjNM9cNHCgL8rYdB9UnsnkcQ5R/XRV1W+tQlj9QjpvcGH5c3PJ6Ol1Qd
+x8o19aomLb/IMz8bnRmzLxWggKQHxLwU3UKjHBiV1aqI/ieka22IqKYkjeYUAyxC
+ZLytynIZRVt0MB/lo7Z2bjctGHSiZ9tkTsgjawE3hotnZ3BOEOkV42099bLLGdcz
+Jq433DsbwThKC0WijeHR4FZEj3H7Gj07PNAlfyM0KeyrZodtcIwvgA4NyBB8mPoV
+dARn5C8hOtDCWzRPba46h9mTzF8D87pdvmZce6k/bBGJfY+YvOpwBXsO3xhCDxqP
+p9gAs6m+qbxsrwvRRrtn6Q==
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/fixtures/gearman/server.key b/tests/fixtures/gearman/server.key
new file mode 100644
index 0000000..c1707b0
--- /dev/null
+++ b/tests/fixtures/gearman/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzoKkaauTNBRry
+1Y5YCNG38IrxW0AH5TP5XdTF/q+Qu1p9onRsACiSZX8YYAo/y6jVbZ3WKihVfVIQ
+w9xrPTCoA0AwMtI8fiK70YwSuGg6gqBBCr8NXOaYsYFJk2Vk+8utlNSmLYlcSTKZ
+R0HbhWNmjH9lj5WngL0XPSbcoogtvet92111qGfBZrg+86B3XJh2/6PCru9Ymufq
+looFog7Q4Qo6Bnz7Dh+h2QjtDmGSFz0dQ9PqP8Jgh3LSfWRk5TrjGsthKszRTZCQ
+DSXc1XcwAqfO21eufP9oTpfc0zTdAOC1tspdP/632q6B0Gf8sSEnMpKmwuGUH3z2
+ZCY6DSE1AgMBAAECggEAaG06YhVKtrYFGK92dU+LPHgnDnGSJATn1kzqacDKqEWD
+Mg7DyBW/gHxpCu6qhrQLjyiO3fbcQ/b7Qqva9K06IDLjmiGxf2GFJ9OGr0ttrLZM
+HAP3VflwRczL8M4z4CVSH7OqfIF0naYgOGPosYo2Y2PCnHSA+EQrqdrvQM1shcot
+8lW368VqlAm8ONgh8z4ZLSDswECgJzWleOSsTBIT0qJ6fXIwnN7akM8Bdyy/dPDD
+PnPvAu1N9KgwrzxKY9WthJ1alKiFQm4Po/TZZApALOtR8zCN4EmDG9izKdfU5FIL
+ZWpVDp0US7a8rbj2e0kf0loRg2bsR2eoJPL7JjJycQKBgQDiHjKnwximtfjqLTtg
+ZOHIL4tTlmeTLNq7ZW69BuJSfI7FTa20piHjny+g3mTvxnCQa/BTSpb6VRHPFcYV
+dVQzdAX6ZMvBZ3YMp9FkY+S9RrjEyimNU9kvJJQBnC1ujen3YuXj6ENFzcmGkvzR
+LZFx3dmFEzfDxOOqzdFTHscGuwKBgQDLXaVBH54yq1fDrXDLG/eEtQsNNyCujIV4
+gp1Z54L34htoDS98dx0L0qZGBEys8I0dGJd9kUBVNu53zDeiJSGW4tHYXQaUpxJH
+0wZDHo59mw3aGvVZ5YP+4uukuNHcX6cUYi2HAv0vwet46L3Kb/utDyyStp1QZw9s
+eucOLGkQzwKBgG3j0yZo0FAk28WjGdos7PWG9aU30TpbcCnmj7zZ3Z/M3O3SZHsI
+yit/L3x02IUW4Zmue2tfMqSSN0d3A39mN/eRiV45IjTp/RsFa+PoEEBUYHNy9GK0
+vzYEBtIJfqLd4TjTHXp3ZEpGSoxWXvuhs6+s64ua3V0NEL/vqq1EpeEFAoGAHa/i
+8tnJvz3SBwenoo7HmEDRhzFX/QMYbNosXDZ2oPcJ5yudlf7RZ6ttiGUSSGCpSOkR
+HEx65rWpJCXUrT/cYmlkFsCluEeXXJLKpDuus1lSMVekH2Zo2WmI2rf8Mr5n5ora
+eI4QJcuaM0FOi2HDjKTdbeFon5cb4ksitaf4AnMCgYB24KyMuOHBAuVlnuf3PSfr
+u3ZxqmcUX0D2BoK+1lw3lgzfQO26Qw5VtkjDBnIPL67IUYRZX2YvXsJPWaRRrF72
+yEqFXDWKbcE+Tl0LxLj6mLW5RKJP8LTybaIBgkyUaLtzTRr+TfK29CC8/FzWGiTf
+oJQozL3TAlvjoadEPrLnjg==
+-----END PRIVATE KEY-----
diff --git a/tests/fixtures/gearman/server.pem b/tests/fixtures/gearman/server.pem
new file mode 100644
index 0000000..1c85fad
--- /dev/null
+++ b/tests/fixtures/gearman/server.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRTCCAi0CCQDnKP1tRJr+1zANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJV
+UzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkF1c3RpbjEdMBsGA1UECgwUT3Bl
+blN0YWNrIEZvdW5kYXRpb24xEzARBgNVBAMMCmdlYXJtYW4tY2EwHhcNMTcwNjE0
+MTQwNjM1WhcNMjcwNjEyMTQwNjM1WjBnMQswCQYDVQQGEwJVUzEOMAwGA1UECAwF
+VGV4YXMxDzANBgNVBAcMBkF1c3RpbjEdMBsGA1UECgwUT3BlblN0YWNrIEZvdW5k
+YXRpb24xGDAWBgNVBAMMD25vZGVwb29sLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALOgqRpq5M0FGvLVjlgI0bfwivFbQAflM/ld1MX+r5C7
+Wn2idGwAKJJlfxhgCj/LqNVtndYqKFV9UhDD3Gs9MKgDQDAy0jx+IrvRjBK4aDqC
+oEEKvw1c5pixgUmTZWT7y62U1KYtiVxJMplHQduFY2aMf2WPlaeAvRc9JtyiiC29
+633bXXWoZ8FmuD7zoHdcmHb/o8Ku71ia5+qWigWiDtDhCjoGfPsOH6HZCO0OYZIX
+PR1D0+o/wmCHctJ9ZGTlOuMay2EqzNFNkJANJdzVdzACp87bV658/2hOl9zTNN0A
+4LW2yl0//rfaroHQZ/yxIScykqbC4ZQffPZkJjoNITUCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAlqcjSBG96JnKcSlw4ntxJiSGja5iuMi3yVpQS8G3ak6i8eGYlqMH
+SCWC96ZfXr/KjVyF3AsD554e54pEAywcFLH4QzZoceWc5L2etfTCa9cInQsiNpvV
+CfvVADRX4Ib7ozb4MJFJFy5OWnhPO6CcknA2KdTergKIichBmR0LvuUZEblwHOcg
+HAwxpZirNofs/i+aXnIgKAIC97WY1S+8SL5cEfdR0Sd9SpbCLVgSdyGhxm0NE2ls
+38jQhwYIVkpYYJd/jsyGtiHCDT4rkSEJlRWYfLXfSkyjtiERASqs/NEgrnbkgp/l
+Sa2wc5cjntNzls2ey7bkpZbgwOvGQVjS7w==
+-----END CERTIFICATE-----
diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py
index 839007d..1124beb 100755
--- a/tests/unit/test_scheduler.py
+++ b/tests/unit/test_scheduler.py
@@ -35,12 +35,36 @@
 import zuul.model
 
 from tests.base import (
+    SSLZuulTestCase,
     ZuulTestCase,
     repack_repo,
     simple_layout,
 )
 
 
+class TestSchedulerSSL(SSLZuulTestCase):
+    tenant_config_file = 'config/single-tenant/main.yaml'
+
+    def test_jobs_executed(self):
+        "Test that jobs are executed and a change is merged"
+
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
+        A.addApproval('code-review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.waitUntilSettled()
+        self.assertEqual(self.getJobFromHistory('project-merge').result,
+                         'SUCCESS')
+        self.assertEqual(self.getJobFromHistory('project-test1').result,
+                         'SUCCESS')
+        self.assertEqual(self.getJobFromHistory('project-test2').result,
+                         'SUCCESS')
+        self.assertEqual(A.data['status'], 'MERGED')
+        self.assertEqual(A.reported, 2)
+        self.assertEqual(self.getJobFromHistory('project-test1').node,
+                         'label1')
+        self.assertIsNone(self.getJobFromHistory('project-test2').node)
+
+
 class TestScheduler(ZuulTestCase):
     tenant_config_file = 'config/single-tenant/main.yaml'
 
diff --git a/zuul/cmd/client.py b/zuul/cmd/client.py
index 3f67a38..d8250c5 100644
--- a/zuul/cmd/client.py
+++ b/zuul/cmd/client.py
@@ -125,6 +125,18 @@
             self.port = self.config.get('gearman', 'port')
         else:
             self.port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            self.ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            self.ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            self.ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            self.ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            self.ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            self.ssl_ca = None
 
         if self.args.func():
             sys.exit(0)
@@ -132,7 +144,8 @@
             sys.exit(1)
 
     def enqueue(self):
-        client = zuul.rpcclient.RPCClient(self.server, self.port)
+        client = zuul.rpcclient.RPCClient(
+            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)
         r = client.enqueue(tenant=self.args.tenant,
                            pipeline=self.args.pipeline,
                            project=self.args.project,
@@ -141,7 +154,8 @@
         return r
 
     def enqueue_ref(self):
-        client = zuul.rpcclient.RPCClient(self.server, self.port)
+        client = zuul.rpcclient.RPCClient(
+            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)
         r = client.enqueue_ref(tenant=self.args.tenant,
                                pipeline=self.args.pipeline,
                                project=self.args.project,
@@ -152,14 +166,16 @@
         return r
 
     def promote(self):
-        client = zuul.rpcclient.RPCClient(self.server, self.port)
+        client = zuul.rpcclient.RPCClient(
+            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)
         r = client.promote(tenant=self.args.tenant,
                            pipeline=self.args.pipeline,
                            change_ids=self.args.changes)
         return r
 
     def show_running_jobs(self):
-        client = zuul.rpcclient.RPCClient(self.server, self.port)
+        client = zuul.rpcclient.RPCClient(
+            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)
         running_items = client.get_running_jobs()
 
         if len(running_items) == 0:
diff --git a/zuul/cmd/scheduler.py b/zuul/cmd/scheduler.py
index 5328bba..d16eb17 100755
--- a/zuul/cmd/scheduler.py
+++ b/zuul/cmd/scheduler.py
@@ -102,7 +102,22 @@
                 host = self.config.get('gearman_server', 'listen_address')
             else:
                 host = None
+            if self.config.has_option('gearman_server', 'ssl_key'):
+                ssl_key = self.config.get('gearman_server', 'ssl_key')
+            else:
+                ssl_key = None
+            if self.config.has_option('gearman_server', 'ssl_cert'):
+                ssl_cert = self.config.get('gearman_server', 'ssl_cert')
+            else:
+                ssl_cert = None
+            if self.config.has_option('gearman_server', 'ssl_ca'):
+                ssl_ca = self.config.get('gearman_server', 'ssl_ca')
+            else:
+                ssl_ca = None
             zuul.lib.gearserver.GearServer(4730,
+                                           ssl_key=ssl_key,
+                                           ssl_cert=ssl_cert,
+                                           ssl_ca=ssl_ca,
                                            host=host,
                                            statsd_host=statsd_host,
                                            statsd_port=statsd_port,
diff --git a/zuul/driver/github/githubconnection.py b/zuul/driver/github/githubconnection.py
index d3779d6..f9f1c27 100644
--- a/zuul/driver/github/githubconnection.py
+++ b/zuul/driver/github/githubconnection.py
@@ -565,7 +565,13 @@
     def getPull(self, project_name, number):
         github = self.getGithubClient(project_name)
         owner, proj = project_name.split('/')
-        probj = github.pull_request(owner, proj, number)
+        for retry in range(5):
+            probj = github.pull_request(owner, proj, number)
+            if probj is not None:
+                break
+            self.log.warning("Pull request #%s of %s/%s returned None!" % (
+                             number, owner, proj))
+            time.sleep(1)
         pr = probj.as_dict()
         pr['files'] = [f.filename for f in probj.files()]
         log_rate_limit(self.log, github)
diff --git a/zuul/executor/client.py b/zuul/executor/client.py
index f6961f3..6ecb27c 100644
--- a/zuul/executor/client.py
+++ b/zuul/executor/client.py
@@ -119,9 +119,21 @@
             port = config.get('gearman', 'port')
         else:
             port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            ssl_ca = None
 
         self.gearman = ZuulGearmanClient(self)
-        self.gearman.addServer(server, port)
+        self.gearman.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
 
         self.cleanup_thread = GearmanCleanup(self)
         self.cleanup_thread.start()
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index 981034d..a29eeb9 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -459,10 +459,22 @@
             port = self.config.get('gearman', 'port')
         else:
             port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            ssl_ca = None
         self.merger_worker = ExecutorMergeWorker(self, 'Zuul Executor Merger')
-        self.merger_worker.addServer(server, port)
+        self.merger_worker.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
         self.executor_worker = gear.TextWorker('Zuul Executor Server')
-        self.executor_worker.addServer(server, port)
+        self.executor_worker.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
         self.log.debug("Waiting for server")
         self.merger_worker.waitForServer()
         self.executor_worker.waitForServer()
@@ -1178,7 +1190,6 @@
                          self.jobdir.root)
             config.write('remote_tmp = %s/.ansible/remote_tmp\n' %
                          self.jobdir.root)
-            config.write('private_key_file = %s\n' % self.private_key_file)
             config.write('retry_files_enabled = False\n')
             config.write('gathering = explicit\n')
             config.write('library = %s\n'
diff --git a/zuul/merger/client.py b/zuul/merger/client.py
index c98f20e..4054df6 100644
--- a/zuul/merger/client.py
+++ b/zuul/merger/client.py
@@ -79,9 +79,21 @@
             port = self.config.get('gearman', 'port')
         else:
             port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            ssl_ca = None
         self.log.debug("Connecting to gearman at %s:%s" % (server, port))
         self.gearman = MergeGearmanClient(self)
-        self.gearman.addServer(server, port)
+        self.gearman.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
         self.log.debug("Waiting for gearman")
         self.gearman.waitForServer()
         self.jobs = set()
diff --git a/zuul/merger/server.py b/zuul/merger/server.py
index 1a32f96..7d7e771 100644
--- a/zuul/merger/server.py
+++ b/zuul/merger/server.py
@@ -54,8 +54,20 @@
             port = self.config.get('gearman', 'port')
         else:
             port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            ssl_ca = None
         self.worker = gear.TextWorker('Zuul Merger')
-        self.worker.addServer(server, port)
+        self.worker.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
         self.log.debug("Waiting for server")
         self.worker.waitForServer()
         self.log.debug("Registering")
diff --git a/zuul/rpcclient.py b/zuul/rpcclient.py
index d980992..6f0d34b 100644
--- a/zuul/rpcclient.py
+++ b/zuul/rpcclient.py
@@ -26,10 +26,10 @@
 class RPCClient(object):
     log = logging.getLogger("zuul.RPCClient")
 
-    def __init__(self, server, port):
+    def __init__(self, server, port, ssl_key=None, ssl_cert=None, ssl_ca=None):
         self.log.debug("Connecting to gearman at %s:%s" % (server, port))
         self.gearman = gear.Client()
-        self.gearman.addServer(server, port)
+        self.gearman.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
         self.log.debug("Waiting for gearman")
         self.gearman.waitForServer()
 
diff --git a/zuul/rpclistener.py b/zuul/rpclistener.py
index 6508e84..0079ab8 100644
--- a/zuul/rpclistener.py
+++ b/zuul/rpclistener.py
@@ -38,9 +38,23 @@
             port = self.config.get('gearman', 'port')
         else:
             port = 4730
+        if self.config.has_option('gearman', 'ssl_key'):
+            ssl_key = self.config.get('gearman', 'ssl_key')
+        else:
+            ssl_key = None
+        if self.config.has_option('gearman', 'ssl_cert'):
+            ssl_cert = self.config.get('gearman', 'ssl_cert')
+        else:
+            ssl_cert = None
+        if self.config.has_option('gearman', 'ssl_ca'):
+            ssl_ca = self.config.get('gearman', 'ssl_ca')
+        else:
+            ssl_ca = None
         self.worker = gear.TextWorker('Zuul RPC Listener')
-        self.worker.addServer(server, port)
+        self.worker.addServer(server, port, ssl_key, ssl_cert, ssl_ca)
+        self.log.debug("Waiting for server")
         self.worker.waitForServer()
+        self.log.debug("Registering")
         self.register()
         self.thread = threading.Thread(target=self.run)
         self.thread.daemon = True