diff --git a/ansible_mitogen/connection.py b/ansible_mitogen/connection.py index b00430ca..7bae8c25 100644 --- a/ansible_mitogen/connection.py +++ b/ansible_mitogen/connection.py @@ -568,6 +568,7 @@ class Connection(ansible.plugins.connection.ConnectionBase): via_vars = self.host_vars[inventory_name] return ansible_mitogen.transport_config.MitogenViaSpec( inventory_name=inventory_name, + play_context=self._play_context, host_vars=dict(via_vars), # TODO: make it lazy become_method=become_method or None, become_user=become_user or None, diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 7af4dc55..15694523 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -430,12 +430,33 @@ class MitogenViaSpec(Spec): having a configruation problem with connection delegation, the answer to your problem lies in the method implementations below! """ - def __init__(self, inventory_name, host_vars, - become_method, become_user): + def __init__(self, inventory_name, host_vars, become_method, become_user, + play_context): + """ + :param str inventory_name: + The inventory name of the intermediary machine, i.e. not the target + machine. + :param dict host_vars: + The HostVars magic dictionary provided by Ansible in task_vars. + :param str become_method: + If the mitogen_via= spec included a become method, the method it + specifies. + :param str become_user: + If the mitogen_via= spec included a become user, the user it + specifies. + :param PlayContext play_context: + For some global values **only**, the PlayContext used to describe + the real target machine. Values from this object are **strictly + restricted** to values that are Ansible-global, e.g. the passwords + specified interactively. + """ self._inventory_name = inventory_name self._host_vars = host_vars self._become_method = become_method self._become_user = become_user + # Dangerous! You may find a variable you want in this object, but it's + # almost certainly for the wrong machine! + self._dangerous_play_context = play_context def transport(self): return ( @@ -479,7 +500,6 @@ class MitogenViaSpec(Spec): def password(self): return optional_secret( - # TODO: Might have to come from PlayContext. self._host_vars.get('ansible_ssh_pass') or self._host_vars.get('ansible_password') ) diff --git a/docs/ansible.rst b/docs/ansible.rst index e6e237d9..f7788011 100644 --- a/docs/ansible.rst +++ b/docs/ansible.rst @@ -246,6 +246,11 @@ container. as duplicate connections between hops, due to not perfectly replicating the configuration Ansible would normally use for the intermediary. + * Intermediary machines cannot use login and become passwords that were + supplied to Ansible interactively. If an intermediary requires a + password, it must be supplied via ``ansible_ssh_pass``, + ``ansible_password``, or ``ansible_become_pass`` inventory variables. + * Automatic tunnelling of SSH-dependent actions, such as the ``synchronize`` module, is not yet supported. This will be added in the 0.3 series. diff --git a/docs/changelog.rst b/docs/changelog.rst index c3c3e8a4..245e87e6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -136,6 +136,14 @@ Fixes repair ``delegate_to`` handling broke default ``ansible_python_interpreter`` handling. Test coverage was added. +* `748f5f67 `_: the + ``ansible_ssh_host`` parameter is respected when ``mitogen_via=`` is active. + +* `21ad299d `_: the + precedence of ``ansible_ssh_user`` and ``ansible_user`` was corrected when + when ``mitogen_via=`` is active. + + Thanks! ~~~~~~~ diff --git a/tests/ansible/hosts/transport_config.hosts b/tests/ansible/hosts/transport_config.hosts index ab83c65d..cb64d87b 100644 --- a/tests/ansible/hosts/transport_config.hosts +++ b/tests/ansible/hosts/transport_config.hosts @@ -18,9 +18,8 @@ tc-remote-addr-explicit-ssh ansible_ssh_host=ansi.ssh.host tc-remote-addr-explicit-host ansible_host=ansi.host tc-remote-addr-explicit-both ansible_ssh_host=a.b.c ansible_host=b.c.d -# remote_addr() -tc-remote-user-unset # defaults to C.DEFAULT_REMOTE_USER -tc-remote-user-explicit-ssh ansible_ssh_user=ansi-ssh-user -tc-remote-user-explicit-user ansible_user=ansi-user -tc-remote-user-explicit-both ansible_user=a.b.c ansible_ssh_user=c.b.a - +# password() +tc-password-unset +tc-password-explicit-ssh ansible_ssh_pass=ansi-ssh-pass +tc-password-explicit-user ansible_password=ansi-pass +tc-password-explicit-both ansible_password=a.b.c ansible_ssh_pass=c.b.a diff --git a/tests/ansible/integration/transport_config/all.yml b/tests/ansible/integration/transport_config/all.yml index 618e72e3..a9880ffc 100644 --- a/tests/ansible/integration/transport_config/all.yml +++ b/tests/ansible/integration/transport_config/all.yml @@ -1,3 +1,4 @@ +- include: password.yml - include: python_path.yml - include: remote_addr.yml - include: remote_user.yml diff --git a/tests/ansible/integration/transport_config/password.yml b/tests/ansible/integration/transport_config/password.yml new file mode 100644 index 00000000..ac236d66 --- /dev/null +++ b/tests/ansible/integration/transport_config/password.yml @@ -0,0 +1,94 @@ +# Each case is followed by mitogen_via= case to test hostvars method. + + +# When no ansible_ssh_pass/ansible_password= is set, password comes via +# interactive input. +- name: integration/transport_config/password.yml + hosts: tc-password-unset + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "" # actually null, but assert_equal limitation + +- hosts: tc-password-unset + vars: {mitogen_via: tc-password-explicit-ssh} + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "ansi-ssh-pass" + - assert_equal: + left: out.result[1].kwargs.password + right: "" + + +# ansible_ssh_user= + +- hosts: tc-password-explicit-ssh + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "ansi-ssh-pass" + +- hosts: tc-password-explicit-ssh + vars: {mitogen_via: tc-password-unset} + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "" + - assert_equal: + left: out.result[1].kwargs.password + right: "ansi-ssh-pass" + + +# ansible_user= + +- hosts: tc-password-explicit-pass + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "ansi-pass" + +- hosts: tc-password-explicit-pass + vars: {mitogen_via: tc-password-unset} + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "" + - assert_equal: + left: out.result[1].kwargs.password + right: "ansi-pass" + + +# both; ansible_ssh_user= takes precedence according to play_context.py. + +- hosts: tc-password-explicit-both + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "c.b.a" + +- hosts: tc-password-explicit-both + vars: {mitogen_via: tc-password-unset} + tasks: + - include: ../_mitogen_only.yml + - {mitogen_get_stack: {}, register: out} + - assert_equal: + left: out.result[0].kwargs.password + right: "" + - assert_equal: + left: out.result[1].kwargs.password + right: "c.b.a"