<gh_stars>0
# Copyright (c) 2020 Citrix Systems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
    connection: ssh_citrix_adc
    short_description: connect via ssh client binary with Citrix ADC bypassing the cli
    description:
        - This connection plugin allows ansible to communicate to the target Citrix ADC via normal ssh command line.
        - The only authentication method that works with this plugin is with ssh key file.
        - The input options supported by this connection plugin are the same as the ssh connection plugin of Ansible.
    author:
     - <NAME> (<EMAIL>)
     - <NAME> (<EMAIL>)
    version_added: "1.0.0"
    options:
      host:
          description: Hostname/ip to connect to.
          default: inventory_hostname
          vars:
               - name: ansible_host
               - name: ansible_ssh_host
      host_key_checking:
          description: Determines if ssh should check host keys
          type: boolean
          ini:
              - section: defaults
                key: 'host_key_checking'
              - section: ssh_connection
                key: 'host_key_checking'
                version_added: '2.5'
          env:
              - name: ANSIBLE_HOST_KEY_CHECKING
              - name: ANSIBLE_SSH_HOST_KEY_CHECKING
                version_added: '2.5'
          vars:
              - name: ansible_host_key_checking
                version_added: '2.5'
              - name: ansible_ssh_host_key_checking
                version_added: '2.5'
      password:
          description: Authentication password for the C(remote_user). Can be supplied as CLI option.
          vars:
              - name: ansible_password
              - name: ansible_ssh_pass
      ssh_args:
          description: Arguments to pass to all ssh cli tools
          default: '-C -o ControlMaster=auto -o ControlPersist=60s'
          ini:
              - section: 'ssh_connection'
                key: 'ssh_args'
          env:
              - name: ANSIBLE_SSH_ARGS
          vars:
              - name: ansible_ssh_args
                version_added: '2.7'
      ssh_common_args:
          description: Common extra args for all ssh CLI tools
          ini:
              - section: 'ssh_connection'
                key: 'ssh_common_args'
                version_added: '2.7'
          env:
              - name: ANSIBLE_SSH_COMMON_ARGS
                version_added: '2.7'
          vars:
              - name: ansible_ssh_common_args
      ssh_executable:
          default: ssh
          description:
            - This defines the location of the ssh binary. It defaults to ``ssh`` which will use the first ssh binary available in $PATH.
            - This option is usually not required, it might be useful when access to system ssh is restricted,
              or when using ssh wrappers to connect to remote hosts.
          env: [{name: ANSIBLE_SSH_EXECUTABLE}]
          ini:
          - {key: ssh_executable, section: ssh_connection}
          #const: ANSIBLE_SSH_EXECUTABLE
          version_added: "2.2"
          vars:
              - name: ansible_ssh_executable
                version_added: '2.7'
      sftp_executable:
          default: sftp
          description:
            - This defines the location of the sftp binary. It defaults to ``sftp`` which will use the first binary available in $PATH.
          env: [{name: ANSIBLE_SFTP_EXECUTABLE}]
          ini:
          - {key: sftp_executable, section: ssh_connection}
          version_added: "2.6"
          vars:
              - name: ansible_sftp_executable
                version_added: '2.7'
      scp_executable:
          default: scp
          description:
            - This defines the location of the scp binary. It defaults to `scp` which will use the first binary available in $PATH.
          env: [{name: ANSIBLE_SCP_EXECUTABLE}]
          ini:
          - {key: scp_executable, section: ssh_connection}
          version_added: "2.6"
          vars:
              - name: ansible_scp_executable
                version_added: '2.7'
      scp_extra_args:
          description: Extra exclusive to the ``scp`` CLI
          vars:
              - name: ansible_scp_extra_args
          env:
            - name: ANSIBLE_SCP_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: scp_extra_args
              section: ssh_connection
              version_added: '2.7'
      sftp_extra_args:
          description: Extra exclusive to the ``sftp`` CLI
          vars:
              - name: ansible_sftp_extra_args
          env:
            - name: ANSIBLE_SFTP_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: sftp_extra_args
              section: ssh_connection
              version_added: '2.7'
      ssh_extra_args:
          description: Extra exclusive to the 'ssh' CLI
          vars:
              - name: ansible_ssh_extra_args
          env:
            - name: ANSIBLE_SSH_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: ssh_extra_args
              section: ssh_connection
              version_added: '2.7'
      retries:
          # constant: ANSIBLE_SSH_RETRIES
          description: Number of attempts to connect.
          default: 3
          type: integer
          env:
            - name: ANSIBLE_SSH_RETRIES
          ini:
            - section: connection
              key: retries
            - section: ssh_connection
              key: retries
          vars:
              - name: ansible_ssh_retries
                version_added: '2.7'
      port:
          description: Remote port to connect to.
          type: int
          default: 22
          ini:
            - section: defaults
              key: remote_port
          env:
            - name: ANSIBLE_REMOTE_PORT
          vars:
            - name: ansible_port
            - name: ansible_ssh_port
      remote_user:
          description:
              - User name with which to login to the remote server, normally set by the remote_user keyword.
              - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally
          ini:
            - section: defaults
              key: remote_user
          env:
            - name: ANSIBLE_REMOTE_USER
          vars:
            - name: ansible_user
            - name: ansible_ssh_user
      pipelining:
          default: ANSIBLE_PIPELINING
          description:
            - Pipelining reduces the number of SSH operations required to execute a module on the remote server,
              by executing many Ansible modules without actual file transfer.
            - This can result in a very significant performance improvement when enabled.
            - However this conflicts with privilege escalation (become).
              For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts,
              which is why this feature is disabled by default.
          env:
            - name: ANSIBLE_PIPELINING
            #- name: ANSIBLE_SSH_PIPELINING
          ini:
            - section: defaults
              key: pipelining
            #- section: ssh_connection
            #  key: pipelining
          type: boolean
          vars:
            - name: ansible_pipelining
            - name: ansible_ssh_pipelining
      private_key_file:
          description:
              - Path to private key file to use for authentication
          ini:
            - section: defaults
              key: private_key_file
          env:
            - name: ANSIBLE_PRIVATE_KEY_FILE
          vars:
            - name: ansible_private_key_file
            - name: ansible_ssh_private_key_file

      control_path:
        description:
          - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution.
          - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting.
        env:
          - name: ANSIBLE_SSH_CONTROL_PATH
        ini:
          - key: control_path
            section: ssh_connection
        vars:
          - name: ansible_control_path
            version_added: '2.7'
      control_path_dir:
        default: ~/.ansible/cp
        description:
          - This sets the directory to use for ssh control path if the control path setting is null.
          - Also, provides the `%(directory)s` variable for the control path setting.
        env:
          - name: ANSIBLE_SSH_CONTROL_PATH_DIR
        ini:
          - section: ssh_connection
            key: control_path_dir
        vars:
          - name: ansible_control_path_dir
            version_added: '2.7'
      sftp_batch_mode:
        default: 'yes'
        description: 'TODO: write it'
        env: [{name: ANSIBLE_SFTP_BATCH_MODE}]
        ini:
        - {key: sftp_batch_mode, section: ssh_connection}
        type: bool
        vars:
          - name: ansible_sftp_batch_mode
            version_added: '2.7'
      scp_if_ssh:
        default: smart
        description:
          - "Prefered method to use when transfering files over ssh"
          - When set to smart, Ansible will try them until one succeeds or they all fail
          - If set to True, it will force 'scp', if False it will use 'sftp'
        env: [{name: ANSIBLE_SCP_IF_SSH}]
        ini:
        - {key: scp_if_ssh, section: ssh_connection}
        vars:
          - name: ansible_scp_if_ssh
            version_added: '2.7'
      use_tty:
        version_added: '2.5'
        default: 'yes'
        description: add -tt to ssh commands to force tty allocation
        env: [{name: ANSIBLE_SSH_USETTY}]
        ini:
        - {key: usetty, section: ssh_connection}
        type: bool
        vars:
          - name: ansible_ssh_use_tty
            version_added: '2.7'
'''

import codecs

from functools import wraps
from ansible.errors import AnsibleError
from ansible.plugins.connection.ssh import Connection as ConnectionSsh

from ansible.utils.display import Display
from ansible.plugins.loader import become_loader

import re

display = Display()


SSHPASS_AVAILABLE = None


class AnsibleControlPersistBrokenPipeError(AnsibleError):
    ''' ControlPersist broken pipe '''
    pass


def _return_tuple_manipulate(func):
    @wraps(func)
    def wrapped(self, *args, **kwargs):
        return_tuple = func(self, *args, **kwargs)
        return_tuple = list(return_tuple)
        subst = ""
        regex = r"(\r\n|\r|\n|)( Done)(\r\n|\r|\n)+"
        return_tuple[1] = re.sub(regex, subst, codecs.decode(return_tuple[1]), 0, re.UNICODE)
        return_tuple = tuple(return_tuple)
        return return_tuple
    return wrapped


def _manipulate_cmd(func):

    @wraps(func)
    def wrapped(self, cmd, *args, **kwargs):
        # Adding the 'shell' command for the citrix adc cli
        if cmd.startswith('ssh_citrix_adc'):
            cmd = cmd.replace('ssh_citrix_adc', '')
        else:
            cmd = type(cmd)("shell ") + cmd
        returncode, stdout, stderr = func(self, cmd, *args, **kwargs)
        return (returncode, stdout, stderr)
    return wrapped


def calculate_become_methods():
    all_methods = []
    for item in become_loader.all():
        # Skip runas
        if item.name == 'runas':
            continue
        all_methods.append(item.name)

    return frozenset(all_methods)


class Connection(ConnectionSsh):
    ''' ssh based connections '''

    transport = 'ssh_citrix_adc'
    has_pipelining = True
    become_methods = calculate_become_methods()
    name = 'ssh_citrix_adc'

    def __init__(self, *args, **kwargs):
        super(Connection, self).__init__(*args, **kwargs)

    @_return_tuple_manipulate
    def _run(self, cmd, in_data, sudoable=True, checkrc=True):
        """Wrapper around _bare_run that retries the connection
        """
        return super(Connection, self)._run(cmd, in_data, sudoable=sudoable, checkrc=checkrc)

    @_manipulate_cmd
    def exec_command(self, cmd, in_data=None, sudoable=True):
        ''' run a command on the remote host '''

        return super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)

# Copyright (c) 2020 Citrix Systems, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
    connection: ssh_citrix_adc
    short_description: connect via ssh client binary with Citrix ADC bypassing the cli
    description:
        - This connection plugin allows ansible to communicate to the target Citrix ADC via normal ssh command line.
        - The only authentication method that works with this plugin is with ssh key file.
        - The input options supported by this connection plugin are the same as the ssh connection plugin of Ansible.
    author:
     - <NAME> (<EMAIL>)
     - <NAME> (<EMAIL>)
    version_added: "1.0.0"
    options:
      host:
          description: Hostname/ip to connect to.
          default: inventory_hostname
          vars:
               - name: ansible_host
               - name: ansible_ssh_host
      host_key_checking:
          description: Determines if ssh should check host keys
          type: boolean
          ini:
              - section: defaults
                key: 'host_key_checking'
              - section: ssh_connection
                key: 'host_key_checking'
                version_added: '2.5'
          env:
              - name: ANSIBLE_HOST_KEY_CHECKING
              - name: ANSIBLE_SSH_HOST_KEY_CHECKING
                version_added: '2.5'
          vars:
              - name: ansible_host_key_checking
                version_added: '2.5'
              - name: ansible_ssh_host_key_checking
                version_added: '2.5'
      password:
          description: Authentication password for the C(remote_user). Can be supplied as CLI option.
          vars:
              - name: ansible_password
              - name: ansible_ssh_pass
      ssh_args:
          description: Arguments to pass to all ssh cli tools
          default: '-C -o ControlMaster=auto -o ControlPersist=60s'
          ini:
              - section: 'ssh_connection'
                key: 'ssh_args'
          env:
              - name: ANSIBLE_SSH_ARGS
          vars:
              - name: ansible_ssh_args
                version_added: '2.7'
      ssh_common_args:
          description: Common extra args for all ssh CLI tools
          ini:
              - section: 'ssh_connection'
                key: 'ssh_common_args'
                version_added: '2.7'
          env:
              - name: ANSIBLE_SSH_COMMON_ARGS
                version_added: '2.7'
          vars:
              - name: ansible_ssh_common_args
      ssh_executable:
          default: ssh
          description:
            - This defines the location of the ssh binary. It defaults to ``ssh`` which will use the first ssh binary available in $PATH.
            - This option is usually not required, it might be useful when access to system ssh is restricted,
              or when using ssh wrappers to connect to remote hosts.
          env: [{name: ANSIBLE_SSH_EXECUTABLE}]
          ini:
          - {key: ssh_executable, section: ssh_connection}
          #const: ANSIBLE_SSH_EXECUTABLE
          version_added: "2.2"
          vars:
              - name: ansible_ssh_executable
                version_added: '2.7'
      sftp_executable:
          default: sftp
          description:
            - This defines the location of the sftp binary. It defaults to ``sftp`` which will use the first binary available in $PATH.
          env: [{name: ANSIBLE_SFTP_EXECUTABLE}]
          ini:
          - {key: sftp_executable, section: ssh_connection}
          version_added: "2.6"
          vars:
              - name: ansible_sftp_executable
                version_added: '2.7'
      scp_executable:
          default: scp
          description:
            - This defines the location of the scp binary. It defaults to `scp` which will use the first binary available in $PATH.
          env: [{name: ANSIBLE_SCP_EXECUTABLE}]
          ini:
          - {key: scp_executable, section: ssh_connection}
          version_added: "2.6"
          vars:
              - name: ansible_scp_executable
                version_added: '2.7'
      scp_extra_args:
          description: Extra exclusive to the ``scp`` CLI
          vars:
              - name: ansible_scp_extra_args
          env:
            - name: ANSIBLE_SCP_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: scp_extra_args
              section: ssh_connection
              version_added: '2.7'
      sftp_extra_args:
          description: Extra exclusive to the ``sftp`` CLI
          vars:
              - name: ansible_sftp_extra_args
          env:
            - name: ANSIBLE_SFTP_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: sftp_extra_args
              section: ssh_connection
              version_added: '2.7'
      ssh_extra_args:
          description: Extra exclusive to the 'ssh' CLI
          vars:
              - name: ansible_ssh_extra_args
          env:
            - name: ANSIBLE_SSH_EXTRA_ARGS
              version_added: '2.7'
          ini:
            - key: ssh_extra_args
              section: ssh_connection
              version_added: '2.7'
      retries:
          # constant: ANSIBLE_SSH_RETRIES
          description: Number of attempts to connect.
          default: 3
          type: integer
          env:
            - name: ANSIBLE_SSH_RETRIES
          ini:
            - section: connection
              key: retries
            - section: ssh_connection
              key: retries
          vars:
              - name: ansible_ssh_retries
                version_added: '2.7'
      port:
          description: Remote port to connect to.
          type: int
          default: 22
          ini:
            - section: defaults
              key: remote_port
          env:
            - name: ANSIBLE_REMOTE_PORT
          vars:
            - name: ansible_port
            - name: ansible_ssh_port
      remote_user:
          description:
              - User name with which to login to the remote server, normally set by the remote_user keyword.
              - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally
          ini:
            - section: defaults
              key: remote_user
          env:
            - name: ANSIBLE_REMOTE_USER
          vars:
            - name: ansible_user
            - name: ansible_ssh_user
      pipelining:
          default: ANSIBLE_PIPELINING
          description:
            - Pipelining reduces the number of SSH operations required to execute a module on the remote server,
              by executing many Ansible modules without actual file transfer.
            - This can result in a very significant performance improvement when enabled.
            - However this conflicts with privilege escalation (become).
              For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts,
              which is why this feature is disabled by default.
          env:
            - name: ANSIBLE_PIPELINING
            #- name: ANSIBLE_SSH_PIPELINING
          ini:
            - section: defaults
              key: pipelining
            #- section: ssh_connection
            #  key: pipelining
          type: boolean
          vars:
            - name: ansible_pipelining
            - name: ansible_ssh_pipelining
      private_key_file:
          description:
              - Path to private key file to use for authentication
          ini:
            - section: defaults
              key: private_key_file
          env:
            - name: ANSIBLE_PRIVATE_KEY_FILE
          vars:
            - name: ansible_private_key_file
            - name: ansible_ssh_private_key_file

      control_path:
        description:
          - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution.
          - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting.
        env:
          - name: ANSIBLE_SSH_CONTROL_PATH
        ini:
          - key: control_path
            section: ssh_connection
        vars:
          - name: ansible_control_path
            version_added: '2.7'
      control_path_dir:
        default: ~/.ansible/cp
        description:
          - This sets the directory to use for ssh control path if the control path setting is null.
          - Also, provides the `%(directory)s` variable for the control path setting.
        env:
          - name: ANSIBLE_SSH_CONTROL_PATH_DIR
        ini:
          - section: ssh_connection
            key: control_path_dir
        vars:
          - name: ansible_control_path_dir
            version_added: '2.7'
      sftp_batch_mode:
        default: 'yes'
        description: 'TODO: write it'
        env: [{name: ANSIBLE_SFTP_BATCH_MODE}]
        ini:
        - {key: sftp_batch_mode, section: ssh_connection}
        type: bool
        vars:
          - name: ansible_sftp_batch_mode
            version_added: '2.7'
      scp_if_ssh:
        default: smart
        description:
          - "Prefered method to use when transfering files over ssh"
          - When set to smart, Ansible will try them until one succeeds or they all fail
          - If set to True, it will force 'scp', if False it will use 'sftp'
        env: [{name: ANSIBLE_SCP_IF_SSH}]
        ini:
        - {key: scp_if_ssh, section: ssh_connection}
        vars:
          - name: ansible_scp_if_ssh
            version_added: '2.7'
      use_tty:
        version_added: '2.5'
        default: 'yes'
        description: add -tt to ssh commands to force tty allocation
        env: [{name: ANSIBLE_SSH_USETTY}]
        ini:
        - {key: usetty, section: ssh_connection}
        type: bool
        vars:
          - name: ansible_ssh_use_tty
            version_added: '2.7'
'''

import codecs

from functools import wraps
from ansible.errors import AnsibleError
from ansible.plugins.connection.ssh import Connection as ConnectionSsh

from ansible.utils.display import Display
from ansible.plugins.loader import become_loader

import re

display = Display()


SSHPASS_AVAILABLE = None


class AnsibleControlPersistBrokenPipeError(AnsibleError):
    ''' ControlPersist broken pipe '''
    pass


def _return_tuple_manipulate(func):
    @wraps(func)
    def wrapped(self, *args, **kwargs):
        return_tuple = func(self, *args, **kwargs)
        return_tuple = list(return_tuple)
        subst = ""
        regex = r"(\r\n|\r|\n|)( Done)(\r\n|\r|\n)+"
        return_tuple[1] = re.sub(regex, subst, codecs.decode(return_tuple[1]), 0, re.UNICODE)
        return_tuple = tuple(return_tuple)
        return return_tuple
    return wrapped


def _manipulate_cmd(func):

    @wraps(func)
    def wrapped(self, cmd, *args, **kwargs):
        # Adding the 'shell' command for the citrix adc cli
        if cmd.startswith('ssh_citrix_adc'):
            cmd = cmd.replace('ssh_citrix_adc', '')
        else:
            cmd = type(cmd)("shell ") + cmd
        returncode, stdout, stderr = func(self, cmd, *args, **kwargs)
        return (returncode, stdout, stderr)
    return wrapped


def calculate_become_methods():
    all_methods = []
    for item in become_loader.all():
        # Skip runas
        if item.name == 'runas':
            continue
        all_methods.append(item.name)

    return frozenset(all_methods)


class Connection(ConnectionSsh):
    ''' ssh based connections '''

    transport = 'ssh_citrix_adc'
    has_pipelining = True
    become_methods = calculate_become_methods()
    name = 'ssh_citrix_adc'

    def __init__(self, *args, **kwargs):
        super(Connection, self).__init__(*args, **kwargs)

    @_return_tuple_manipulate
    def _run(self, cmd, in_data, sudoable=True, checkrc=True):
        """Wrapper around _bare_run that retries the connection
        """
        return super(Connection, self)._run(cmd, in_data, sudoable=sudoable, checkrc=checkrc)

    @_manipulate_cmd
    def exec_command(self, cmd, in_data=None, sudoable=True):
        ''' run a command on the remote host '''

        return super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
# Copyright (c) 2020 Citrix Systems, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. connection: ssh_citrix_adc     short_description: connect via ssh client binary with Citrix ADC bypassing the cli     description:         - This connection plugin allows ansible to communicate to the target Citrix ADC via normal ssh command line.         - The only authentication method that works with this plugin is with ssh key file.         - The input options supported by this connection plugin are the same as the ssh connection plugin of Ansible.     author:      - <NAME> (<EMAIL>)      - <NAME> (<EMAIL>)     version_added: "1.0.0"     options:       host:           description: Hostname/ip to connect to.           default: inventory_hostname           vars:                - name: ansible_host                - name: ansible_ssh_host       host_key_checking:           description: Determines if ssh should check host keys           type: boolean           ini:               - section: defaults                 key: 'host_key_checking'               - section: ssh_connection                 key: 'host_key_checking'                 version_added: '2.5'           env:               - name: ANSIBLE_HOST_KEY_CHECKING               - name: ANSIBLE_SSH_HOST_KEY_CHECKING                 version_added: '2.5'           vars:               - name: ansible_host_key_checking                 version_added: '2.5'               - name: ansible_ssh_host_key_checking                 version_added: '2.5'       password:           description: Authentication password for the C(remote_user). Can be supplied as CLI option.           vars:               - name: ansible_password               - name: ansible_ssh_pass       ssh_args:           description: Arguments to pass to all ssh cli tools           default: '-C -o ControlMaster=auto -o ControlPersist=60s'           ini:               - section: 'ssh_connection'                 key: 'ssh_args'           env:               - name: ANSIBLE_SSH_ARGS           vars:               - name: ansible_ssh_args                 version_added: '2.7'       ssh_common_args:           description: Common extra args for all ssh CLI tools           ini:               - section: 'ssh_connection'                 key: 'ssh_common_args'                 version_added: '2.7'           env:               - name: ANSIBLE_SSH_COMMON_ARGS                 version_added: '2.7'           vars:               - name: ansible_ssh_common_args       ssh_executable:           default: ssh           description:             - This defines the location of the ssh binary. It defaults to ``ssh`` which will use the first ssh binary available in $PATH.             - This option is usually not required, it might be useful when access to system ssh is restricted,               or when using ssh wrappers to connect to remote hosts.           env: [{name: ANSIBLE_SSH_EXECUTABLE}]           ini:           - {key: ssh_executable, section: ssh_connection}           #const: ANSIBLE_SSH_EXECUTABLE           version_added: "2.2"           vars:               - name: ansible_ssh_executable                 version_added: '2.7'       sftp_executable:           default: sftp           description:             - This defines the location of the sftp binary. It defaults to ``sftp`` which will use the first binary available in $PATH.           env: [{name: ANSIBLE_SFTP_EXECUTABLE}]           ini:           - {key: sftp_executable, section: ssh_connection}           version_added: "2.6"           vars:               - name: ansible_sftp_executable                 version_added: '2.7'       scp_executable:           default: scp           description:             - This defines the location of the scp binary. It defaults to `scp` which will use the first binary available in $PATH.           env: [{name: ANSIBLE_SCP_EXECUTABLE}]           ini:           - {key: scp_executable, section: ssh_connection}           version_added: "2.6"           vars:               - name: ansible_scp_executable                 version_added: '2.7'       scp_extra_args:           description: Extra exclusive to the ``scp`` CLI           vars:               - name: ansible_scp_extra_args           env:             - name: ANSIBLE_SCP_EXTRA_ARGS               version_added: '2.7'           ini:             - key: scp_extra_args               section: ssh_connection               version_added: '2.7'       sftp_extra_args:           description: Extra exclusive to the ``sftp`` CLI           vars:               - name: ansible_sftp_extra_args           env:             - name: ANSIBLE_SFTP_EXTRA_ARGS               version_added: '2.7'           ini:             - key: sftp_extra_args               section: ssh_connection               version_added: '2.7'       ssh_extra_args:           description: Extra exclusive to the 'ssh' CLI           vars:               - name: ansible_ssh_extra_args           env:             - name: ANSIBLE_SSH_EXTRA_ARGS               version_added: '2.7'           ini:             - key: ssh_extra_args               section: ssh_connection               version_added: '2.7'       retries:           # constant: ANSIBLE_SSH_RETRIES           description: Number of attempts to connect.           default: 3           type: integer           env:             - name: ANSIBLE_SSH_RETRIES           ini:             - section: connection               key: retries             - section: ssh_connection               key: retries           vars:               - name: ansible_ssh_retries                 version_added: '2.7'       port:           description: Remote port to connect to.           type: int           default: 22           ini:             - section: defaults               key: remote_port           env:             - name: ANSIBLE_REMOTE_PORT           vars:             - name: ansible_port             - name: ansible_ssh_port       remote_user:           description:               - User name with which to login to the remote server, normally set by the remote_user keyword.               - If no user is supplied, Ansible will let the ssh client binary choose the user as it normally           ini:             - section: defaults               key: remote_user           env:             - name: ANSIBLE_REMOTE_USER           vars:             - name: ansible_user             - name: ansible_ssh_user       pipelining:           default: ANSIBLE_PIPELINING           description:             - Pipelining reduces the number of SSH operations required to execute a module on the remote server,               by executing many Ansible modules without actual file transfer.             - This can result in a very significant performance improvement when enabled.             - However this conflicts with privilege escalation (become).               For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts,               which is why this feature is disabled by default.           env:             - name: ANSIBLE_PIPELINING             #- name: ANSIBLE_SSH_PIPELINING           ini:             - section: defaults               key: pipelining             #- section: ssh_connection             #  key: pipelining           type: boolean           vars:             - name: ansible_pipelining             - name: ansible_ssh_pipelining       private_key_file:           description:               - Path to private key file to use for authentication           ini:             - section: defaults               key: private_key_file           env:             - name: ANSIBLE_PRIVATE_KEY_FILE           vars:             - name: ansible_private_key_file             - name: ansible_ssh_private_key_file        control_path:         description:           - This is the location to save ssh's ControlPath sockets, it uses ssh's variable substitution.           - Since 2.3, if null, ansible will generate a unique hash. Use `%(directory)s` to indicate where to use the control dir path setting.         env:           - name: ANSIBLE_SSH_CONTROL_PATH         ini:           - key: control_path             section: ssh_connection         vars:           - name: ansible_control_path             version_added: '2.7'       control_path_dir:         default: ~/.ansible/cp         description:           - This sets the directory to use for ssh control path if the control path setting is null.           - Also, provides the `%(directory)s` variable for the control path setting.         env:           - name: ANSIBLE_SSH_CONTROL_PATH_DIR         ini:           - section: ssh_connection             key: control_path_dir         vars:           - name: ansible_control_path_dir             version_added: '2.7'       sftp_batch_mode:         default: 'yes'         description: 'TODO: write it'         env: [{name: ANSIBLE_SFTP_BATCH_MODE}]         ini:         - {key: sftp_batch_mode, section: ssh_connection}         type: bool         vars:           - name: ansible_sftp_batch_mode             version_added: '2.7'       scp_if_ssh:         default: smart         description:           - "Prefered method to use when transfering files over ssh"           - When set to smart, Ansible will try them until one succeeds or they all fail           - If set to True, it will force 'scp', if False it will use 'sftp'         env: [{name: ANSIBLE_SCP_IF_SSH}]         ini:         - {key: scp_if_ssh, section: ssh_connection}         vars:           - name: ansible_scp_if_ssh             version_added: '2.7'       use_tty:         version_added: '2.5'         default: 'yes'         description: add -tt to ssh commands to force tty allocation         env: [{name: ANSIBLE_SSH_USETTY}]         ini:         - {key: usetty, section: ssh_connection}         type: bool         vars:           - name: ansible_ssh_use_tty             version_added: '2.7' ControlPersist broken pipe # Adding the 'shell' command for the citrix adc cli # Skip runas ssh based connections Wrapper around _bare_run that retries the connection run a command on the remote host