Merge commit 'refs/pull/377/head' of github.com:dw/mitogen into dmw

(Pull #377)

Changes:
- additional_parameters -> extra_args
- Merge with kubectl changes from dmw branch
- Update docs
- Remove unused username class member
- Avoid mutable kubectl_args class member
- Use six.iteritems
issue72
David Wilson 6 years ago
commit 4c81eba599

@ -133,11 +133,10 @@ def _connect_kubectl(spec):
return { return {
'method': 'kubectl', 'method': 'kubectl',
'kwargs': { 'kwargs': {
'username': spec['remote_user'],
'pod': spec['remote_addr'], 'pod': spec['remote_addr'],
#'container': spec['container'],
'python_path': spec['python_path'], 'python_path': spec['python_path'],
'connect_timeout': spec['ansible_ssh_timeout'] or spec['timeout'], 'connect_timeout': spec['ansible_ssh_timeout'] or spec['timeout'],
'kubectl_args': spec['extra_args'],
} }
} }
@ -393,6 +392,8 @@ def config_from_play_context(transport, inventory_name, connection):
connection.get_task_var('mitogen_machinectl_path'), connection.get_task_var('mitogen_machinectl_path'),
'mitogen_ssh_debug_level': 'mitogen_ssh_debug_level':
connection.get_task_var('mitogen_ssh_debug_level'), connection.get_task_var('mitogen_ssh_debug_level'),
'extra_args':
connection.get_extra_args(),
} }
@ -790,6 +791,14 @@ class Connection(ansible.plugins.connection.ConnectionBase):
ansible_mitogen.target.create_fork_child ansible_mitogen.target.create_fork_child
) )
def get_extra_args(self):
"""
Overridden by connections/mitogen_kubectl.py to a list of additional
arguments for the command.
"""
# TODO: maybe use this for SSH too.
return []
def get_default_cwd(self): def get_default_cwd(self):
""" """
Overridden by connections/mitogen_local.py to emulate behaviour of CWD Overridden by connections/mitogen_local.py to emulate behaviour of CWD

@ -31,6 +31,9 @@ from __future__ import absolute_import
import os.path import os.path
import sys import sys
import ansible.plugins.connection.kubectl
from ansible.module_utils.six import iteritems
try: try:
import ansible_mitogen import ansible_mitogen
except ImportError: except ImportError:
@ -43,3 +46,11 @@ import ansible_mitogen.connection
class Connection(ansible_mitogen.connection.Connection): class Connection(ansible_mitogen.connection.Connection):
transport = 'kubectl' transport = 'kubectl'
def get_extra_args(self):
parameters = []
for key, option in iteritems(ansible.plugins.connection.kubectl.CONNECTION_OPTIONS):
if self.get_task_var('ansible_' + key) is not None:
parameters += [ option, self.get_task_var('ansible_' + key) ]
return parameters

@ -589,7 +589,7 @@ Router Class
Filename or complete path to the ``jexec`` binary. ``PATH`` will be Filename or complete path to the ``jexec`` binary. ``PATH`` will be
searched if given as a filename. Defaults to ``/usr/sbin/jexec``. searched if given as a filename. Defaults to ``/usr/sbin/jexec``.
.. method:: kubectl (pid=None, container=None, kubectl_path=None, username=None, \**kwargs) .. method:: kubectl (pod, kubectl_path=None, kubectl_args=None, \**kwargs)
Construct a context in a container via the Kubernetes ``kubectl`` Construct a context in a container via the Kubernetes ``kubectl``
program. program.
@ -598,16 +598,11 @@ Router Class
:param str pod: :param str pod:
Kubernetes pod to connect to. Kubernetes pod to connect to.
:param str container:
Optional container within pod to connect to. If the pod has only
one container, this parameter is not required. Defaults to
:data:`None`.
:param str kubectl_path: :param str kubectl_path:
Filename or complete path to the ``kubectl`` binary. ``PATH`` will Filename or complete path to the ``kubectl`` binary. ``PATH`` will
be searched if given as a filename. Defaults to ``kubectl``. be searched if given as a filename. Defaults to ``kubectl``.
:param str username: :param list kubectl_args:
Optional username to authenticate to the Kubernetes API server Additional arguments to pass to the ``kubectl`` command.
with. within the container to :func:`setuid` to.
.. method:: lxc (container, lxc_attach_path=None, \**kwargs) .. method:: lxc (container, lxc_attach_path=None, \**kwargs)
@ -729,7 +724,7 @@ Router Class
:class:`mitogen.core.StreamError` to be raised, and that :class:`mitogen.core.StreamError` to be raised, and that
attributes of the stream match the actual behaviour of ``sudo``. attributes of the stream match the actual behaviour of ``sudo``.
.. method:: ssh (hostname, username=None, ssh_path=None, port=None, check_host_keys='enforce', password=None, identity_file=None, identities_only=True, compression=True, \**kwargs) .. method:: ssh (hostname, username=None, ssh_path=None, ssh_args=None, port=None, check_host_keys='enforce', password=None, identity_file=None, identities_only=True, compression=True, \**kwargs)
Construct a remote context over an OpenSSH ``ssh`` invocation. Construct a remote context over an OpenSSH ``ssh`` invocation.
@ -747,6 +742,8 @@ Router Class
the username to use. the username to use.
:param str ssh_path: :param str ssh_path:
Absolute or relative path to ``ssh``. Defaults to ``ssh``. Absolute or relative path to ``ssh``. Defaults to ``ssh``.
:param list ssh_args:
Additional arguments to pass to the SSH command.
:param int port: :param int port:
Port number to connect to; default is unspecified, which causes SSH Port number to connect to; default is unspecified, which causes SSH
to pick the port number. to pick the port number.

@ -41,7 +41,8 @@ Enhancements
`uri <http://docs.ansible.com/ansible/latest/modules/uri_module.html>`_). See `uri <http://docs.ansible.com/ansible/latest/modules/uri_module.html>`_). See
:ref:`ansible_tempfiles` for a complete description. :ref:`ansible_tempfiles` for a complete description.
* `#376 <https://github.com/dw/mitogen/pull/376>`_: the ``kubectl`` connection * `#376 <https://github.com/dw/mitogen/pull/376>`_,
`#377 <https://github.com/dw/mitogen/pull/377>`_: the ``kubectl`` connection
type is now supported. Contributed by Yannig Perré. type is now supported. Contributed by Yannig Perré.
* `084c0ac0 <https://github.com/dw/mitogen/commit/084c0ac0>`_: avoid a * `084c0ac0 <https://github.com/dw/mitogen/commit/084c0ac0>`_: avoid a

@ -35,41 +35,31 @@ import mitogen.parent
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class Stream(mitogen.parent.Stream): class Stream(mitogen.parent.Stream):
child_is_immediate_subprocess = True child_is_immediate_subprocess = True
pod = None pod = None
container = None
username = None
kubectl_path = 'kubectl' kubectl_path = 'kubectl'
kubectl_args = None
# TODO: better way of capturing errors such as "No such container." # TODO: better way of capturing errors such as "No such container."
create_child_args = { create_child_args = {
'merge_stdio': True 'merge_stdio': True
} }
def construct(self, pod, container=None, kubectl_path=None, username=None, def construct(self, pod, kubectl_path=None, kubectl_args=None, **kwargs):
**kwargs):
super(Stream, self).construct(**kwargs) super(Stream, self).construct(**kwargs)
assert pod
self.pod = pod self.pod = pod
if container:
self.container = container
if kubectl_path: if kubectl_path:
self.kubectl_path = kubectl_path self.kubectl_path = kubectl_path
if username: self.kubectl_args = kubectl_args or []
self.username = username
def connect(self): def connect(self):
super(Stream, self).connect() super(Stream, self).connect()
self.name = u'kubectl.' + (self.pod) + str(self.container) self.name = u'kubectl.%s%s' % (self.pod, self.kubectl_args)
def get_boot_command(self): def get_boot_command(self):
args = ['exec', '-it', self.pod] bits = [self.kubectl_path] + self.kubectl_args + ['exec', '-it', self.pod]
if self.username: return bits + ["--"] + super(Stream, self).get_boot_command()
args += ['--username=' + self.username]
if self.container:
args += ['--container=' + self.container]
bits = [self.kubectl_path]
return bits + args + [ "--" ] + super(Stream, self).get_boot_command()

@ -1,8 +1,11 @@
--- ---
- name: "Create pod" - name: "Create pod"
tags: always tags: create
hosts: localhost hosts: localhost
vars:
pod_count: 10
loop_count: 5
gather_facts: no gather_facts: no
tasks: tasks:
- name: Create a test pod - name: Create a test pod
@ -19,7 +22,10 @@
- name: python2 - name: python2
image: python:2 image: python:2
args: [ "sleep", "100000" ] args: [ "sleep", "100000" ]
loop: "{{ range(10)|list }}" - name: python3
image: python:3
args: [ "sleep", "100000" ]
loop: "{{ range(pod_count|int)|list }}"
- name: "Wait pod to be running" - name: "Wait pod to be running"
debug: { msg: "pod is running" } debug: { msg: "pod is running" }
@ -30,7 +36,7 @@
delay: 2 delay: 2
vars: vars:
pod_def: "{{lookup('k8s', kind='Pod', namespace='default', resource_name='test-pod-' ~ item)}}" pod_def: "{{lookup('k8s', kind='Pod', namespace='default', resource_name='test-pod-' ~ item)}}"
loop: "{{ range(10)|list }}" loop: "{{ range(pod_count|int)|list }}"
- name: "Add pod to pods group" - name: "Add pod to pods group"
add_host: add_host:
@ -39,45 +45,95 @@
ansible_connection: "kubectl" ansible_connection: "kubectl"
changed_when: no changed_when: no
tags: "always" tags: "always"
loop: "{{ range(10)|list }}" loop: "{{ range(pod_count|int)|list }}"
- name: "Test kubectl connection (default strategy)" - name: "Test kubectl connection (default strategy)"
tags: default tags: default
hosts: pods hosts: pods
strategy: "linear" strategy: "linear"
vars:
pod_count: 10
loop_count: 5
gather_facts: no gather_facts: no
tasks: tasks:
- name: "Simple shell with linear" - name: "Simple shell with linear"
shell: ls /tmp shell: ls /tmp
loop: [ 1, 2, 3, 4, 5 ] loop: "{{ range(loop_count|int)|list }}"
- name: "Simple file with linear" - name: "Simple file with linear"
file: file:
path: "/etc" path: "/etc"
state: directory state: directory
loop: [ 1, 2, 3, 4, 5 ] loop: "{{ range(loop_count|int)|list }}"
- block:
- name: "Check python version on python3 container"
command: python --version
vars:
ansible_kubectl_container: python3
register: _
- assert: { that: "'Python 3' in _.stdout" }
- debug: var=_.stdout,_.stderr
run_once: yes
- name: "Check python version on default container"
command: python --version
register: _
- assert: { that: "'Python 2' in _.stderr" }
- debug: var=_.stdout,_.stderr
run_once: yes
- name: "Test kubectl connection (mitogen strategy)" - name: "Test kubectl connection (mitogen strategy)"
tags: mitogen tags: mitogen
hosts: pods hosts: pods
strategy: "mitogen_linear" strategy: "mitogen_linear"
vars:
pod_count: 10
loop_count: 5
gather_facts: no gather_facts: no
tasks: tasks:
- name: "Simple shell with mitogen" - name: "Simple shell with mitogen"
shell: ls /tmp shell: ls /tmp
loop: [ 1, 2, 3, 4, 5 ] loop: "{{ range(loop_count|int)|list }}"
- name: "Simple file with mitogen" - name: "Simple file with mitogen"
file: file:
path: "/etc" path: "/etc"
state: directory state: directory
loop: [ 1, 2, 3, 4, 5 ] loop: "{{ range(loop_count|int)|list }}"
register: _
- block:
- name: "Check python version on python3 container"
command: python --version
vars:
ansible_kubectl_container: python3
register: _
- assert: { that: "'Python 3' in _.stdout" }
- debug: var=_.stdout,_.stderr
run_once: yes
- name: "Check python version on default container"
command: python --version
register: _
- assert: { that: "'Python 2' in _.stderr" }
- debug: var=_.stdout,_.stderr
run_once: yes
tags: check
- name: "Destroy pod" - name: "Destroy pod"
tags: cleanup tags: cleanup
hosts: localhost hosts: pods
gather_facts: no gather_facts: no
vars:
ansible_connection: "local"
tasks: tasks:
- name: Destroy pod - name: Destroy pod
k8s: k8s:
@ -86,6 +142,5 @@
apiVersion: v1 apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: test-pod-{{item}} name: "{{inventory_hostname}}"
namespace: default namespace: default
loop: "{{ range(10)|list }}"

Loading…
Cancel
Save