@@ -649,6 +649,66 @@ def test_fail_json_when_ansible_runner_not_found(self):
649649 self .fake_ktbw .main )
650650 self .assertIn ('ansible-runner' , error .result ['msg' ])
651651
652+ def test_runner_exec_uses_ansible_user_when_no_user_param (self ):
653+ """user=None must exec ansible-runner as 'ansible', not as root.
654+
655+ Podman serialises user=None as null in ExecCreate; some daemon
656+ versions interpret null as UID 0 (root), which breaks openstacksdk
657+ lookups because HOME becomes /root instead of /var/lib/ansible.
658+ """
659+ self .mock_ansible_module .params ['user' ] = None
660+
661+ with mock .patch .object (self .fake_ktbw , '_push_private_data_dir' ), \
662+ mock .patch .object (self .fake_ktbw , '_parse_runner_result' ,
663+ return_value = {'changed' : False }):
664+ self .fake_ktbw .main ()
665+
666+ # call[0]=check_runner, call[1]=ansible-runner, call[2]=cleanup
667+ runner_call = self .mock_container .exec_run .call_args_list [1 ]
668+ self .assertEqual ('ansible' , runner_call .kwargs .get ('user' ))
669+
670+ def test_runner_exec_sets_home_to_pdd_basedir_for_ansible_user (self ):
671+ """HOME must be set to _PDD_BASEDIR to finds clouds.yaml."""
672+ self .mock_ansible_module .params ['user' ] = None
673+
674+ with mock .patch .object (self .fake_ktbw , '_push_private_data_dir' ), \
675+ mock .patch .object (self .fake_ktbw , '_parse_runner_result' ,
676+ return_value = {'changed' : False }):
677+ self .fake_ktbw .main ()
678+
679+ runner_call = self .mock_container .exec_run .call_args_list [1 ]
680+ env = runner_call .kwargs .get ('environment' , {})
681+ self .assertEqual (kolla_toolbox ._PDD_BASEDIR , env .get ('HOME' ))
682+
683+ def test_runner_exec_uses_explicit_user_param (self ):
684+ """When user='rabbitmq', ansible-runner must exec as 'rabbitmq'."""
685+ self .mock_ansible_module .params ['user' ] = 'rabbitmq'
686+
687+ with mock .patch .object (self .fake_ktbw , '_push_private_data_dir' ), \
688+ mock .patch .object (self .fake_ktbw , '_parse_runner_result' ,
689+ return_value = {'changed' : False }):
690+ self .fake_ktbw .main ()
691+
692+ runner_call = self .mock_container .exec_run .call_args_list [1 ]
693+ self .assertEqual ('rabbitmq' , runner_call .kwargs .get ('user' ))
694+
695+ def test_runner_exec_no_home_override_for_non_ansible_user (self ):
696+ """HOME must not be overridden for non-ansible users.
697+
698+ Forcing HOME=/var/lib/ansible when running as rabbitmq causes
699+ PermissionError because rabbitmq cannot write to ansible's home.
700+ """
701+ self .mock_ansible_module .params ['user' ] = 'rabbitmq'
702+
703+ with mock .patch .object (self .fake_ktbw , '_push_private_data_dir' ), \
704+ mock .patch .object (self .fake_ktbw , '_parse_runner_result' ,
705+ return_value = {'changed' : False }):
706+ self .fake_ktbw .main ()
707+
708+ runner_call = self .mock_container .exec_run .call_args_list [1 ]
709+ env = runner_call .kwargs .get ('environment' , {})
710+ self .assertNotIn ('HOME' , env )
711+
652712
653713class TestModuleInteraction (TestKollaToolboxModule ):
654714 """Class focused on testing user input data from playbook."""
0 commit comments