diff --git a/releasenotes/notes/ansible-shell-type-d76d84b940d21eea.yaml b/releasenotes/notes/ansible-shell-type-d76d84b940d21eea.yaml new file mode 100644 index 0000000000..95cc72f3d7 --- /dev/null +++ b/releasenotes/notes/ansible-shell-type-d76d84b940d21eea.yaml @@ -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. diff --git a/tests/base.py b/tests/base.py index 1b0c6791e6..6afd36ddda 100644 --- a/tests/base.py +++ b/tests/base.py @@ -3369,6 +3369,7 @@ class FakeNodepool(object): self.attributes = None self.resources = None self.python_path = 'auto' + self.shell_type = None def stop(self): self._running = False @@ -3466,6 +3467,7 @@ class FakeNodepool(object): private_ipv4=None, public_ipv6=None, python_path=self.python_path, + shell_type=self.shell_type, allocated_to=request_id, state='ready', state_time=now, diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py index 2652f7f4f5..baca6e053e 100644 --- a/tests/unit/test_executor.py +++ b/tests/unit/test_executor.py @@ -474,6 +474,30 @@ class TestAnsibleJob(ZuulTestCase): host['host_vars']['ansible_ssh_common_args'], '-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): config_file = 'zuul-executor-hostname.conf' diff --git a/tests/unit/test_inventory.py b/tests/unit/test_inventory.py index 024e438a44..3dbc078d05 100644 --- a/tests/unit/test_inventory.py +++ b/tests/unit/test_inventory.py @@ -27,10 +27,12 @@ class TestInventoryBase(ZuulTestCase): tenant_config_file = 'config/inventory/main.yaml' use_gerrit = True - def setUp(self, python_path=None): + def setUp(self, python_path=None, shell_type=None): super(TestInventoryBase, self).setUp() if 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.gearman_server.hold_jobs_in_queue = True @@ -141,6 +143,36 @@ class TestInventoryPythonPath(TestInventoryBase): 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): def test_auto_python_ansible28_inventory(self): @@ -183,6 +215,8 @@ class TestInventory(TestInventoryBase): node_vars = inventory['all']['hosts'][node_name] self.assertEqual( 'auto', node_vars['ansible_python_interpreter']) + self.assertNotIn( + 'ansible_shell_type', node_vars) self.assertIn('zuul', inventory['all']['vars']) self.assertIn('attempts', inventory['all']['vars']['zuul']) self.assertEqual(1, inventory['all']['vars']['zuul']['attempts']) diff --git a/zuul/executor/server.py b/zuul/executor/server.py index f59d1b48a0..7360878ba4 100644 --- a/zuul/executor/server.py +++ b/zuul/executor/server.py @@ -1590,6 +1590,10 @@ class AnsibleJob(object): host_vars['ansible_kubectl_context'] = \ node.get('kubectl_context') + shell_type = node.get('shell_type') + if shell_type: + host_vars['ansible_shell_type'] = shell_type + host_keys = [] for key in node.get('host_keys', []): if port != 22: