executor: add support for custom ansible_port

This change adds 'ssh_port' to the Node class so that zuul-executor can
use a custom ssh server when it is set by nodepool provider.

Change-Id: Icdac6cd41dded0e46fba5d14c31f40810f73b74a
diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py
old mode 100644
new mode 100755
index 39b6070..7b76802
--- a/tests/unit/test_executor.py
+++ b/tests/unit/test_executor.py
@@ -18,6 +18,9 @@
 import logging
 import time
 
+import zuul.executor.server
+import zuul.model
+
 from tests.base import ZuulTestCase, simple_layout
 
 
@@ -305,3 +308,27 @@
         ]
 
         self.assertBuildStates(states, projects)
+
+
+class TestAnsibleJob(ZuulTestCase):
+    tenant_config_file = 'config/ansible/main.yaml'
+
+    def setUp(self):
+        super(TestAnsibleJob, self).setUp()
+        job = zuul.model.Job('test')
+        job.unique = 'test'
+        self.test_job = zuul.executor.server.AnsibleJob(self.executor_server,
+                                                        job)
+
+    def test_getHostList_host_keys(self):
+        # Test without ssh_port set
+        node = {'name': 'fake-host',
+                'host_keys': ['fake-host-key'],
+                'interface_ip': 'localhost'}
+        keys = self.test_job.getHostList({'nodes': [node]})[0]['host_keys']
+        self.assertEqual(keys[0], 'localhost fake-host-key')
+
+        # Test with custom ssh_port set
+        node['ssh_port'] = 22022
+        keys = self.test_job.getHostList({'nodes': [node]})[0]['host_keys']
+        self.assertEqual(keys[0], '[localhost]:22022 fake-host-key')
diff --git a/zuul/executor/client.py b/zuul/executor/client.py
index 6ecb27c..55bc2aa 100644
--- a/zuul/executor/client.py
+++ b/zuul/executor/client.py
@@ -296,6 +296,7 @@
                               host_keys=node.host_keys,
                               provider=node.provider,
                               region=node.region,
+                              ssh_port=node.ssh_port,
                               interface_ip=node.interface_ip,
                               public_ipv6=node.public_ipv6,
                               public_ipv4=node.public_ipv4))
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index f2aedba..83b233e 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -923,9 +923,11 @@
             # results in the wrong thing being in interface_ip
             # TODO(jeblair): Move this notice to the docs.
             ip = node.get('interface_ip')
+            port = node.get('ssh_port', 22)
             host_vars = dict(
                 ansible_host=ip,
                 ansible_user=self.executor_server.default_username,
+                ansible_port=port,
                 nodepool=dict(
                     az=node.get('az'),
                     provider=node.get('provider'),
@@ -933,7 +935,10 @@
 
             host_keys = []
             for key in node.get('host_keys'):
-                host_keys.append("%s %s" % (ip, key))
+                if port != 22:
+                    host_keys.append("[%s]:%s %s" % (ip, port, key))
+                else:
+                    host_keys.append("%s %s" % (ip, key))
 
             hosts.append(dict(
                 name=node['name'],
diff --git a/zuul/model.py b/zuul/model.py
index 610b9b6..1496268 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -367,6 +367,7 @@
         self.public_ipv4 = None
         self.private_ipv4 = None
         self.public_ipv6 = None
+        self.ssh_port = 22
         self._keys = []
         self.az = None
         self.provider = None