5656
5757LOG = logging .getLogger (__name__ )
5858
59+ task_vars_msg = (
60+ 'could not recover task_vars. This means some connection '
61+ 'settings may erroneously be reset to their defaults. '
62+ 'Please report a bug if you encounter this message.'
63+ )
64+
5965
6066def get_remote_name (spec ):
6167 """
@@ -486,15 +492,9 @@ class Connection(ansible.plugins.connection.ConnectionBase):
486492 # the case of the synchronize module.
487493 #
488494
489- #: Set to the host name as it appears in inventory by on_action_run().
490- inventory_hostname = None
491-
492495 #: Set to task_vars by on_action_run().
493496 _task_vars = None
494497
495- #: Set to 'hostvars' by on_action_run()
496- host_vars = None
497-
498498 #: Set by on_action_run()
499499 delegate_to_hostname = None
500500
@@ -527,12 +527,10 @@ def on_action_run(self, task_vars, delegate_to_hostname, loader_basedir):
527527 :param str loader_basedir:
528528 Loader base directory; see :attr:`loader_basedir`.
529529 """
530- self .inventory_hostname = task_vars ['inventory_hostname' ]
531530 self ._task_vars = task_vars
532- self .host_vars = task_vars ['hostvars' ]
533531 self .delegate_to_hostname = delegate_to_hostname
534532 self .loader_basedir = loader_basedir
535- self ._mitogen_reset ( mode = 'put' )
533+ self ._put_connection ( )
536534
537535 def _get_task_vars (self ):
538536 """
@@ -552,8 +550,10 @@ def _get_task_vars(self):
552550 for new connections to be constructed in addition to the preconstructed
553551 connection passed into any running action.
554552 """
555- f = sys ._getframe ()
553+ if self ._task_vars is not None :
554+ return self ._task_vars
556555
556+ f = sys ._getframe ()
557557 while f :
558558 if f .f_code .co_name == 'run' :
559559 f_locals = f .f_locals
@@ -571,9 +571,23 @@ def _get_task_vars(self):
571571
572572 f = f .f_back
573573
574- LOG .warning ('could not recover task_vars. This means some connection '
575- 'settings may erroneously be reset to their defaults. '
576- 'Please report a bug if you encounter this message.' )
574+ raise ansible .errors .AnsibleConnectionFailure (task_vars_msg )
575+
576+ def get_host_vars (self , inventory_hostname ):
577+ """
578+ Fetch the HostVars for a host.
579+
580+ :returns:
581+ Variables dictionary or :data:`None`.
582+ :raises ansible.errors.AnsibleConnectionFailure:
583+ Task vars unavailable.
584+ """
585+ task_vars = self ._get_task_vars ()
586+ hostvars = task_vars .get ('hostvars' )
587+ if hostvars :
588+ return hostvars .get (inventory_hostname )
589+
590+ raise ansible .errors .AnsibleConnectionFailure (task_vars_msg )
577591
578592 def get_task_var (self , key , default = None ):
579593 """
@@ -586,17 +600,16 @@ def get_task_var(self, key, default=None):
586600 does not make sense to extract connection-related configuration for the
587601 delegated-to machine from them.
588602 """
589- task_vars = self ._task_vars or self ._get_task_vars ()
590- if task_vars is not None :
591- if self .delegate_to_hostname is None :
603+ task_vars = self ._get_task_vars ()
604+ if self .delegate_to_hostname is None :
605+ if key in task_vars :
606+ return task_vars [key ]
607+ else :
608+ delegated_vars = task_vars ['ansible_delegated_vars' ]
609+ if self .delegate_to_hostname in delegated_vars :
610+ task_vars = delegated_vars [self .delegate_to_hostname ]
592611 if key in task_vars :
593612 return task_vars [key ]
594- else :
595- delegated_vars = task_vars ['ansible_delegated_vars' ]
596- if self .delegate_to_hostname in delegated_vars :
597- task_vars = delegated_vars [self .delegate_to_hostname ]
598- if key in task_vars :
599- return task_vars [key ]
600613
601614 return default
602615
@@ -628,15 +641,15 @@ def _spec_from_via(self, proxied_inventory_name, via_spec):
628641
629642 # must use __contains__ to avoid a TypeError for a missing host on
630643 # Ansible 2.3.
631- if self .host_vars is None or inventory_name not in self .host_vars :
644+ via_vars = self .get_host_vars (inventory_name )
645+ if via_vars is None :
632646 raise ansible .errors .AnsibleConnectionFailure (
633647 self .unknown_via_msg % (
634648 via_spec ,
635649 proxied_inventory_name ,
636650 )
637651 )
638652
639- via_vars = self .host_vars [inventory_name ]
640653 return ansible_mitogen .transport_config .MitogenViaSpec (
641654 inventory_name = inventory_name ,
642655 play_context = self ._play_context ,
@@ -712,7 +725,7 @@ def _build_stack(self):
712725 connection = self ,
713726 play_context = self ._play_context ,
714727 transport = self .transport ,
715- inventory_name = self .inventory_hostname ,
728+ inventory_name = self .get_task_var ( ' inventory_hostname' ) ,
716729 )
717730 stack = self ._stack_from_spec (spec )
718731 return spec .inventory_name (), stack
@@ -778,18 +791,16 @@ def _connect(self):
778791
779792 inventory_name , stack = self ._build_stack ()
780793 worker_model = ansible_mitogen .process .get_worker_model ()
781- self .binding = worker_model .get_binding (inventory_name )
794+ self .binding = worker_model .get_binding (
795+ mitogen .utils .cast (inventory_name )
796+ )
782797 self ._connect_stack (stack )
783798
784- def _mitogen_reset (self , mode ):
799+ def _put_connection (self ):
785800 """
786801 Forget everything we know about the connected context. This function
787802 cannot be called _reset() since that name is used as a public API by
788803 Ansible 2.4 wait_for_connection plug-in.
789-
790- :param str mode:
791- Name of ContextService method to use to discard the context, either
792- 'put' or 'reset'.
793804 """
794805 if not self .context :
795806 return
@@ -798,7 +809,7 @@ def _mitogen_reset(self, mode):
798809 mitogen .service .call (
799810 call_context = self .binding .get_service_context (),
800811 service_name = 'ansible_mitogen.services.ContextService' ,
801- method_name = mode ,
812+ method_name = 'put' ,
802813 context = self .context
803814 )
804815
@@ -813,24 +824,11 @@ def close(self):
813824 gracefully shut down, and wait for shutdown to complete. Safe to call
814825 multiple times.
815826 """
816- self ._mitogen_reset ( mode = 'put' )
827+ self ._put_connection ( )
817828 if self .binding :
818829 self .binding .close ()
819830 self .binding = None
820831
821- def _reset_find_task_vars (self ):
822- """
823- Monsterous hack: since "meta: reset_connection" does not run from an
824- action, we cannot capture task variables via :meth:`on_action_run`.
825- Instead walk the parent frames searching for the `all_vars` local from
826- StrategyBase._execute_meta(). If this fails, just leave task_vars
827- unset, likely causing a subtly wrong configuration to be selected.
828- """
829- frame = sys ._getframe ()
830- while frame and not self ._task_vars :
831- self ._task_vars = frame .f_locals .get ('all_vars' )
832- frame = frame .f_back
833-
834832 reset_compat_msg = (
835833 'Mitogen only supports "reset_connection" on Ansible 2.5.6 or later'
836834 )
@@ -842,20 +840,31 @@ def reset(self):
842840 the 'disconnected' state, and informs ContextService the connection is
843841 bad somehow, and should be shut down and discarded.
844842 """
845- if self ._task_vars is None :
846- self ._reset_find_task_vars ()
847-
848843 if self ._play_context .remote_addr is None :
849844 # <2.5.6 incorrectly populate PlayContext for reset_connection
850845 # https://github.com/ansible/ansible/issues/27520
851846 raise ansible .errors .AnsibleConnectionFailure (
852847 self .reset_compat_msg
853848 )
854849
855- self ._connect ()
856- self ._mitogen_reset (mode = 'reset' )
857- self .binding .close ()
858- self .binding = None
850+ # Clear out state in case we were ever connected.
851+ self .close ()
852+
853+ inventory_name , stack = self ._build_stack ()
854+ if self ._play_context .become :
855+ stack = stack [:- 1 ]
856+
857+ worker_model = ansible_mitogen .process .get_worker_model ()
858+ binding = worker_model .get_binding (inventory_name )
859+ try :
860+ mitogen .service .call (
861+ call_context = binding .get_service_context (),
862+ service_name = 'ansible_mitogen.services.ContextService' ,
863+ method_name = 'reset' ,
864+ stack = mitogen .utils .cast (list (stack )),
865+ )
866+ finally :
867+ binding .close ()
859868
860869 # Compatibility with Ansible 2.4 wait_for_connection plug-in.
861870 _reset = reset
0 commit comments