Use shell-type config from nodepool

Ansible needs to know which shell type the node uses to operate
correctly, especially for ssh connections for windows nodes because
otherwise ansible defaults to trying bash. Nodepool now allows this
setting in most driver configurations and this change makes Zuul
utilize that setting in the inventory file.

Change-Id: I55389ae8fa30be70c3939737f8c67282aad0ae47
This commit is contained in:
Albin Vass 2021-02-12 14:31:12 +01:00 committed by Daniel Blixt
parent 3461d6e192
commit 85c7dc1665
5 changed files with 75 additions and 1 deletions

View File

@ -0,0 +1,10 @@
---
features:
- |
Zuul now honors the shell-type configuration from nodepool and
uses it to set ansible_shell_type, a setting that is required
when connecting to Windows workers over ssh.
For Linux workers, there is a long standing ansible issue with
using non-default ansible_shell_type and become, so this feature
is primarily targeting Windows workers.

View File

@ -3369,6 +3369,7 @@ class FakeNodepool(object):
self.attributes = None self.attributes = None
self.resources = None self.resources = None
self.python_path = 'auto' self.python_path = 'auto'
self.shell_type = None
def stop(self): def stop(self):
self._running = False self._running = False
@ -3466,6 +3467,7 @@ class FakeNodepool(object):
private_ipv4=None, private_ipv4=None,
public_ipv6=None, public_ipv6=None,
python_path=self.python_path, python_path=self.python_path,
shell_type=self.shell_type,
allocated_to=request_id, allocated_to=request_id,
state='ready', state='ready',
state_time=now, state_time=now,

View File

@ -474,6 +474,30 @@ class TestAnsibleJob(ZuulTestCase):
host['host_vars']['ansible_ssh_common_args'], host['host_vars']['ansible_ssh_common_args'],
'-o StrictHostKeyChecking=false') '-o StrictHostKeyChecking=false')
def test_getHostList_shell_type(self):
# Test without shell type set
node = {'name': 'fake-host',
'host_keys': ['fake-host-key'],
'interface_ip': 'localhost'}
host = self.test_job.getHostList({'nodes': [node],
'host_vars': {},
'vars': {},
'groups': [],
})[0]
self.assertNotIn('ansible_shell_type', host['host_vars'])
# Test with custom shell type set.
node['shell_type'] = 'cmd'
host = self.test_job.getHostList({'nodes': [node],
'host_vars': {},
'vars': {},
'groups': [],
})[0]
self.assertIn('ansible_shell_type', host['host_vars'])
self.assertEqual(
host['host_vars']['ansible_shell_type'],
'cmd')
class TestExecutorHostname(ZuulTestCase): class TestExecutorHostname(ZuulTestCase):
config_file = 'zuul-executor-hostname.conf' config_file = 'zuul-executor-hostname.conf'

View File

@ -27,10 +27,12 @@ class TestInventoryBase(ZuulTestCase):
tenant_config_file = 'config/inventory/main.yaml' tenant_config_file = 'config/inventory/main.yaml'
use_gerrit = True use_gerrit = True
def setUp(self, python_path=None): def setUp(self, python_path=None, shell_type=None):
super(TestInventoryBase, self).setUp() super(TestInventoryBase, self).setUp()
if python_path: if python_path:
self.fake_nodepool.python_path = python_path self.fake_nodepool.python_path = python_path
if shell_type:
self.fake_nodepool.shell_type = shell_type
self.executor_server.hold_jobs_in_build = True self.executor_server.hold_jobs_in_build = True
self.gearman_server.hold_jobs_in_queue = True self.gearman_server.hold_jobs_in_queue = True
@ -141,6 +143,36 @@ class TestInventoryPythonPath(TestInventoryBase):
self.waitUntilSettled() self.waitUntilSettled()
class TestInventoryShellType(TestInventoryBase):
def setUp(self):
super(TestInventoryShellType, self).setUp(shell_type='cmd')
def test_single_inventory(self):
inventory = self._get_build_inventory('single-inventory')
all_nodes = ('ubuntu-xenial',)
self.assertIn('all', inventory)
self.assertIn('hosts', inventory['all'])
self.assertIn('vars', inventory['all'])
for node_name in all_nodes:
self.assertIn(node_name, inventory['all']['hosts'])
node_vars = inventory['all']['hosts'][node_name]
self.assertEqual(
'cmd', node_vars['ansible_shell_type'])
self.assertIn('zuul', inventory['all']['vars'])
z_vars = inventory['all']['vars']['zuul']
self.assertIn('executor', z_vars)
self.assertIn('src_root', z_vars['executor'])
self.assertIn('job', z_vars)
self.assertEqual(z_vars['job'], 'single-inventory')
self.assertEqual(z_vars['message'], 'QQ==')
self.executor_server.release()
self.waitUntilSettled()
class TestInventoryAutoPython(TestInventoryBase): class TestInventoryAutoPython(TestInventoryBase):
def test_auto_python_ansible28_inventory(self): def test_auto_python_ansible28_inventory(self):
@ -183,6 +215,8 @@ class TestInventory(TestInventoryBase):
node_vars = inventory['all']['hosts'][node_name] node_vars = inventory['all']['hosts'][node_name]
self.assertEqual( self.assertEqual(
'auto', node_vars['ansible_python_interpreter']) 'auto', node_vars['ansible_python_interpreter'])
self.assertNotIn(
'ansible_shell_type', node_vars)
self.assertIn('zuul', inventory['all']['vars']) self.assertIn('zuul', inventory['all']['vars'])
self.assertIn('attempts', inventory['all']['vars']['zuul']) self.assertIn('attempts', inventory['all']['vars']['zuul'])
self.assertEqual(1, inventory['all']['vars']['zuul']['attempts']) self.assertEqual(1, inventory['all']['vars']['zuul']['attempts'])

View File

@ -1590,6 +1590,10 @@ class AnsibleJob(object):
host_vars['ansible_kubectl_context'] = \ host_vars['ansible_kubectl_context'] = \
node.get('kubectl_context') node.get('kubectl_context')
shell_type = node.get('shell_type')
if shell_type:
host_vars['ansible_shell_type'] = shell_type
host_keys = [] host_keys = []
for key in node.get('host_keys', []): for key in node.get('host_keys', []):
if port != 22: if port != 22: