issue #340: add connection delegation tests.
This commit is contained in:
parent
aed8fb531b
commit
916e46621b
|
@ -566,7 +566,9 @@ class Connection(ansible.plugins.connection.ConnectionBase):
|
|||
def _build_stack(self):
|
||||
"""
|
||||
Construct a list of dictionaries representing the connection
|
||||
configuration between the controller and the target.
|
||||
configuration between the controller and the target. This is
|
||||
additionally used by the integration tests "mitogen_get_stack" action
|
||||
to fetch the would-be connection configuration.
|
||||
"""
|
||||
if hasattr(self._play_context, 'delegate_to'):
|
||||
target_config = config_from_hostvars(
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# vim: syntax=dosini
|
||||
|
||||
[connection-delegation-test]
|
||||
cd-bastion
|
||||
cd-rack11 mitogen_via=ssh-user@cd-bastion
|
||||
|
@ -13,3 +15,37 @@ cdc-rack11a-docker mitogen_via=docker-admin@cdc-rack11a ansible_connection=docke
|
|||
|
||||
[conn-delegation]
|
||||
cd-user1 ansible_user=mitogen__user1 ansible_connection=mitogen_sudo mitogen_via=target
|
||||
|
||||
|
||||
# Connection delegation scenarios. It's impossible to connection to them, but
|
||||
# you can inspect the would-be config via "mitogen_get_stack" action.
|
||||
[cd-no-connect]
|
||||
# Normal inventory host, no aliasing.
|
||||
cd-normal ansible_connection=mitogen_doas ansible_user=normal-user
|
||||
# Inventory host that is really a different host.
|
||||
cd-alias ansible_connection=ssh ansible_user=alias-user ansible_host=alias-host
|
||||
|
||||
# Via one normal host.
|
||||
cd-normal-normal mitogen_via=cd-normal
|
||||
# Via one aliased host.
|
||||
cd-normal-alias mitogen_via=cd-alias
|
||||
|
||||
# newuser@host via host with explicit username.
|
||||
cd-newuser-normal-normal mitogen_via=cd-normal ansible_user=newuser-normal-normal-user
|
||||
|
||||
# doas:newuser via host.
|
||||
cd-newuser-doas-normal mitogen_via=cd-normal ansible_connection=mitogen_doas ansible_user=newuser-doas-normal-user
|
||||
|
||||
|
||||
# Connection Delegation issue #340 reproduction.
|
||||
# Path to jails is SSH to H -> mitogen_sudo to root -> jail to J
|
||||
|
||||
[issue340]
|
||||
# 'target' plays the role of the normal host machine H.
|
||||
# 'mitogen__sudo1' plays the role of root@H via mitogen_sudo.
|
||||
# 'mitogen__user1' plays the role of root@J via mitogen__user1.
|
||||
# 'mitogen__user2' plays the role of E, the delgate_to target for certs.
|
||||
|
||||
i340-root ansible_user=mitogen__sudo1 ansible_connection=mitogen_sudo mitogen_via=target
|
||||
i340-jail ansible_user=mitogen__user1 ansible_connection=mitogen_sudo mitogen_via=i340-root
|
||||
i340-certs ansible_user=mitogen__user2 ansible_connection=mitogen_sudo mitogen_via=target
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
- import_playbook: become/all.yml
|
||||
- import_playbook: connection_loader/all.yml
|
||||
- import_playbook: context_service/all.yml
|
||||
- import_playbook: delegation/all.yml
|
||||
- import_playbook: glibc_caches/all.yml
|
||||
- import_playbook: local/all.yml
|
||||
- import_playbook: module_utils/all.yml
|
||||
- import_playbook: playbook_semantics/all.yml
|
||||
|
@ -15,4 +17,3 @@
|
|||
- import_playbook: runner/all.yml
|
||||
- import_playbook: ssh/all.yml
|
||||
- import_playbook: strategy/all.yml
|
||||
- import_playbook: glibc_caches/all.yml
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
- import_playbook: stack_construction.yml
|
|
@ -0,0 +1,311 @@
|
|||
# https://github.com/dw/mitogen/issues/251
|
||||
|
||||
# ansible_mitogen.connection internally reinterprets Ansible state into a
|
||||
# 'connection stack' -- this is just a list of dictionaries specifying a
|
||||
# sequence of proxied Router connection methods and their kwargs used to
|
||||
# establish the connection. That list is passed to ContextService, which loops
|
||||
# over the stack specifying via=(None or previous entry) for each connection
|
||||
# method.
|
||||
|
||||
# mitogen_get_stack is a magic action that returns the stack, so we can test
|
||||
# all kinds of scenarios without actually needing a real environmnt.
|
||||
|
||||
# Updating this file? Install 'pprintpp' and hack lib/callbacks/nice_stdout.py
|
||||
# to use it instead of the built-in function, then simply s/'/'/ to get the
|
||||
# cutpasteable formatted dicts below. WARNING: remove the trailing comma from
|
||||
# the result list element, it seems to cause assert to silently succeed!
|
||||
|
||||
|
||||
- name: integration/delegation/stack_construction.yml
|
||||
hosts: cd-normal
|
||||
any_errors_fatal: true
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
"kwargs": {
|
||||
"connect_timeout": 10,
|
||||
"doas_path": None,
|
||||
"password": None,
|
||||
"python_path": ["/usr/bin/python"],
|
||||
"username": "normal-user",
|
||||
},
|
||||
"method": "doas",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-normal
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
delegate_to: cd-alias
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'alias-host',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': None,
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': 'alias-user',
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-alias
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'alias-host',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': ['/usr/bin/python'],
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': 'alias-user',
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-normal-normal
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'connect_timeout': 10,
|
||||
'doas_path': None,
|
||||
'password': None,
|
||||
'python_path': None,
|
||||
'username': 'normal-user',
|
||||
},
|
||||
'method': 'doas',
|
||||
},
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'cd-normal-normal',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': ['/usr/bin/python'],
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': None,
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-normal-alias
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'alias-host',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': None,
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': 'alias-user',
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'cd-normal-alias',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': ['/usr/bin/python'],
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': None,
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-newuser-normal-normal
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'connect_timeout': 10,
|
||||
'doas_path': None,
|
||||
'password': None,
|
||||
'python_path': None,
|
||||
'username': 'normal-user',
|
||||
},
|
||||
'method': 'doas',
|
||||
},
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'cd-newuser-normal-normal',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': ['/usr/bin/python'],
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': 'newuser-normal-normal-user',
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-newuser-normal-normal
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
delegate_to: cd-alias
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'check_host_keys': 'ignore',
|
||||
'connect_timeout': 10,
|
||||
'hostname': 'alias-host',
|
||||
'identity_file': None,
|
||||
'password': None,
|
||||
'port': None,
|
||||
'python_path': None,
|
||||
'ssh_args': [
|
||||
'-o',
|
||||
'ForwardAgent=yes',
|
||||
'-o',
|
||||
'ControlMaster=auto',
|
||||
'-o',
|
||||
'ControlPersist=60s',
|
||||
],
|
||||
'ssh_debug_level': None,
|
||||
'ssh_path': 'ssh',
|
||||
'username': 'alias-user',
|
||||
},
|
||||
'method': 'ssh',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
- hosts: cd-newuser-doas-normal
|
||||
tasks:
|
||||
- mitogen_get_stack:
|
||||
register: out
|
||||
- assert:
|
||||
that: |
|
||||
out.result == [
|
||||
{
|
||||
'kwargs': {
|
||||
'connect_timeout': 10,
|
||||
'doas_path': None,
|
||||
'password': None,
|
||||
'python_path': None,
|
||||
'username': 'normal-user',
|
||||
},
|
||||
'method': 'doas',
|
||||
},
|
||||
{
|
||||
'kwargs': {
|
||||
'connect_timeout': 10,
|
||||
'doas_path': None,
|
||||
'password': None,
|
||||
'python_path': ['/usr/bin/python'],
|
||||
'username': 'newuser-doas-normal-user',
|
||||
},
|
||||
'method': 'doas',
|
||||
},
|
||||
]
|
|
@ -0,0 +1,22 @@
|
|||
"""
|
||||
Fetch the connection configuration stack that would be used to connect to a
|
||||
target, without actually connecting to it.
|
||||
"""
|
||||
|
||||
import ansible_mitogen.connection
|
||||
|
||||
from ansible.plugins.action import ActionBase
|
||||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
if not isinstance(self._connection,
|
||||
ansible_mitogen.connection.Connection):
|
||||
return {
|
||||
'skipped': True,
|
||||
}
|
||||
|
||||
return {
|
||||
'changed': True,
|
||||
'result': self._connection._build_stack(),
|
||||
}
|
Loading…
Reference in New Issue