summaryrefslogtreecommitdiffstats
path: root/test/integration/targets/connection
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/integration/targets/connection/aliases1
-rwxr-xr-xtest/integration/targets/connection/test.sh22
-rw-r--r--test/integration/targets/connection/test_connection.yml43
-rw-r--r--test/integration/targets/connection/test_reset_connection.yml5
-rw-r--r--test/integration/targets/connection_delegation/action_plugins/delegation_action.py12
-rw-r--r--test/integration/targets/connection_delegation/aliases6
-rw-r--r--test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py45
-rw-r--r--test/integration/targets/connection_delegation/inventory.ini1
-rwxr-xr-xtest/integration/targets/connection_delegation/runme.sh9
-rw-r--r--test/integration/targets/connection_delegation/test.yml23
-rw-r--r--test/integration/targets/connection_local/aliases2
-rwxr-xr-xtest/integration/targets/connection_local/runme.sh14
-rw-r--r--test/integration/targets/connection_local/test_connection.inventory7
-rw-r--r--test/integration/targets/connection_paramiko_ssh/aliases5
-rwxr-xr-xtest/integration/targets/connection_paramiko_ssh/runme.sh7
-rwxr-xr-xtest/integration/targets/connection_paramiko_ssh/test.sh14
-rw-r--r--test/integration/targets/connection_paramiko_ssh/test_connection.inventory7
-rw-r--r--test/integration/targets/connection_psrp/aliases4
-rw-r--r--test/integration/targets/connection_psrp/files/empty.txt0
-rwxr-xr-xtest/integration/targets/connection_psrp/runme.sh24
-rw-r--r--test/integration/targets/connection_psrp/test_connection.inventory.j29
-rw-r--r--test/integration/targets/connection_psrp/tests.yml133
-rw-r--r--test/integration/targets/connection_remote_is_local/aliases2
-rw-r--r--test/integration/targets/connection_remote_is_local/connection_plugins/remote_is_local.py25
-rw-r--r--test/integration/targets/connection_remote_is_local/tasks/main.yml15
-rw-r--r--test/integration/targets/connection_remote_is_local/test.yml8
-rw-r--r--test/integration/targets/connection_ssh/aliases3
-rw-r--r--test/integration/targets/connection_ssh/check_ssh_defaults.yml29
-rw-r--r--test/integration/targets/connection_ssh/files/port_overrride_ssh.cfg2
-rwxr-xr-xtest/integration/targets/connection_ssh/posix.sh14
-rwxr-xr-xtest/integration/targets/connection_ssh/runme.sh81
-rw-r--r--test/integration/targets/connection_ssh/test_connection.inventory7
-rw-r--r--test/integration/targets/connection_ssh/test_ssh_defaults.cfg5
-rw-r--r--test/integration/targets/connection_ssh/verify_config.yml21
-rw-r--r--test/integration/targets/connection_windows_ssh/aliases5
-rwxr-xr-xtest/integration/targets/connection_windows_ssh/runme.sh54
-rw-r--r--test/integration/targets/connection_windows_ssh/test_connection.inventory.j212
-rw-r--r--test/integration/targets/connection_windows_ssh/tests.yml32
-rw-r--r--test/integration/targets/connection_windows_ssh/tests_fetch.yml41
-rwxr-xr-xtest/integration/targets/connection_windows_ssh/windows.sh25
-rw-r--r--test/integration/targets/connection_winrm/aliases5
-rwxr-xr-xtest/integration/targets/connection_winrm/runme.sh23
-rw-r--r--test/integration/targets/connection_winrm/test_connection.inventory.j210
-rw-r--r--test/integration/targets/connection_winrm/tests.yml28
44 files changed, 840 insertions, 0 deletions
diff --git a/test/integration/targets/connection/aliases b/test/integration/targets/connection/aliases
new file mode 100644
index 0000000..136c05e
--- /dev/null
+++ b/test/integration/targets/connection/aliases
@@ -0,0 +1 @@
+hidden
diff --git a/test/integration/targets/connection/test.sh b/test/integration/targets/connection/test.sh
new file mode 100755
index 0000000..6e16a87
--- /dev/null
+++ b/test/integration/targets/connection/test.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -eux
+
+[ -f "${INVENTORY}" ]
+
+ansible-playbook test_connection.yml -i "${INVENTORY}" "$@"
+
+# Check that connection vars do not appear in the output
+# https://github.com/ansible/ansible/pull/70853
+trap "rm out.txt" EXIT
+
+ansible all -i "${INVENTORY}" -m set_fact -a "testing=value" -v | tee out.txt
+if grep 'ansible_host' out.txt
+then
+ echo "FAILURE: Connection vars in output"
+ exit 1
+else
+ echo "SUCCESS: Connection vars not found"
+fi
+
+ansible-playbook test_reset_connection.yml -i "${INVENTORY}" "$@"
diff --git a/test/integration/targets/connection/test_connection.yml b/test/integration/targets/connection/test_connection.yml
new file mode 100644
index 0000000..2169942
--- /dev/null
+++ b/test/integration/targets/connection/test_connection.yml
@@ -0,0 +1,43 @@
+- hosts: "{{ target_hosts }}"
+ gather_facts: no
+ serial: 1
+ tasks:
+
+ ### raw with unicode arg and output
+
+ - name: raw with unicode arg and output
+ raw: echo 汉语
+ register: command
+ - name: check output of raw with unicode arg and output
+ assert:
+ that:
+ - "'汉语' in command.stdout"
+ - command is changed # as of 2.2, raw should default to changed: true for consistency w/ shell/command/script modules
+
+ ### copy local file with unicode filename and content
+
+ - name: create local file with unicode filename and content
+ local_action: lineinfile dest={{ local_tmp }}-汉语/汉语.txt create=true line=汉语
+ - name: remove remote file with unicode filename and content
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语/汉语.txt state=absent"
+ - name: create remote directory with unicode name
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=directory"
+ - name: copy local file with unicode filename and content
+ action: "{{ action_prefix }}copy src={{ local_tmp }}-汉语/汉语.txt dest={{ remote_tmp }}-汉语/汉语.txt"
+
+ ### fetch remote file with unicode filename and content
+
+ - name: remove local file with unicode filename and content
+ local_action: file path={{ local_tmp }}-汉语/汉语.txt state=absent
+ - name: fetch remote file with unicode filename and content
+ fetch: src={{ remote_tmp }}-汉语/汉语.txt dest={{ local_tmp }}-汉语/汉语.txt fail_on_missing=true validate_checksum=true flat=true
+
+ ### remove local and remote temp files
+
+ - name: remove local temp file
+ local_action: file path={{ local_tmp }}-汉语 state=absent
+ - name: remove remote temp file
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=absent"
+
+ ### test wait_for_connection plugin
+ - wait_for_connection:
diff --git a/test/integration/targets/connection/test_reset_connection.yml b/test/integration/targets/connection/test_reset_connection.yml
new file mode 100644
index 0000000..2f6cb8d
--- /dev/null
+++ b/test/integration/targets/connection/test_reset_connection.yml
@@ -0,0 +1,5 @@
+- hosts: "{{ target_hosts }}"
+ gather_facts: no
+ tasks:
+ # https://github.com/ansible/ansible/issues/65812
+ - meta: reset_connection
diff --git a/test/integration/targets/connection_delegation/action_plugins/delegation_action.py b/test/integration/targets/connection_delegation/action_plugins/delegation_action.py
new file mode 100644
index 0000000..9d419e7
--- /dev/null
+++ b/test/integration/targets/connection_delegation/action_plugins/delegation_action.py
@@ -0,0 +1,12 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.plugins.action import ActionBase
+
+
+class ActionModule(ActionBase):
+
+ def run(self, tmp=None, task_vars=None):
+ return {
+ 'remote_password': self._connection.get_option('remote_password'),
+ }
diff --git a/test/integration/targets/connection_delegation/aliases b/test/integration/targets/connection_delegation/aliases
new file mode 100644
index 0000000..6c96566
--- /dev/null
+++ b/test/integration/targets/connection_delegation/aliases
@@ -0,0 +1,6 @@
+shippable/posix/group3
+context/controller
+skip/freebsd # No sshpass
+skip/osx # No sshpass
+skip/macos # No sshpass
+skip/rhel # No sshpass
diff --git a/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py b/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py
new file mode 100644
index 0000000..f61846c
--- /dev/null
+++ b/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py
@@ -0,0 +1,45 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+DOCUMENTATION = """
+author: Ansible Core Team
+connection: delegation_connection
+short_description: Test connection for delegated host check
+description:
+- Some further description that you don't care about.
+options:
+ remote_password:
+ description: The remote password
+ type: str
+ vars:
+ - name: ansible_password
+ # Tests that an aliased key gets the -k option which hardcodes the value to password
+ aliases:
+ - password
+"""
+
+from ansible.plugins.connection import ConnectionBase
+
+
+class Connection(ConnectionBase):
+
+ transport = 'delegation_connection'
+ has_pipelining = True
+
+ def __init__(self, *args, **kwargs):
+ super(Connection, self).__init__(*args, **kwargs)
+
+ def _connect(self):
+ super(Connection, self)._connect()
+
+ def exec_command(self, cmd, in_data=None, sudoable=True):
+ super(Connection, self).exec_command(cmd, in_data, sudoable)
+
+ def put_file(self, in_path, out_path):
+ super(Connection, self).put_file(in_path, out_path)
+
+ def fetch_file(self, in_path, out_path):
+ super(Connection, self).fetch_file(in_path, out_path)
+
+ def close(self):
+ super(Connection, self).close()
diff --git a/test/integration/targets/connection_delegation/inventory.ini b/test/integration/targets/connection_delegation/inventory.ini
new file mode 100644
index 0000000..e7f846d
--- /dev/null
+++ b/test/integration/targets/connection_delegation/inventory.ini
@@ -0,0 +1 @@
+my_host ansible_host=127.0.0.1 ansible_connection=delegation_connection
diff --git a/test/integration/targets/connection_delegation/runme.sh b/test/integration/targets/connection_delegation/runme.sh
new file mode 100755
index 0000000..4d50724
--- /dev/null
+++ b/test/integration/targets/connection_delegation/runme.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -ux
+
+echo "Checking if sshpass is present"
+command -v sshpass 2>&1 || exit 0
+echo "sshpass is present, continuing with test"
+
+sshpass -p my_password ansible-playbook -i inventory.ini test.yml -k "$@"
diff --git a/test/integration/targets/connection_delegation/test.yml b/test/integration/targets/connection_delegation/test.yml
new file mode 100644
index 0000000..678bef5
--- /dev/null
+++ b/test/integration/targets/connection_delegation/test.yml
@@ -0,0 +1,23 @@
+---
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - name: test connection receives -k from play_context when delegating
+ delegation_action:
+ delegate_to: my_host
+ register: result
+
+ - assert:
+ that:
+ - result.remote_password == 'my_password'
+
+ - name: ensure vars set for that host take precedence over -k
+ delegation_action:
+ delegate_to: my_host
+ vars:
+ ansible_password: other_password
+ register: result
+
+ - assert:
+ that:
+ - result.remote_password == 'other_password'
diff --git a/test/integration/targets/connection_local/aliases b/test/integration/targets/connection_local/aliases
new file mode 100644
index 0000000..9390a2b
--- /dev/null
+++ b/test/integration/targets/connection_local/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group5
+needs/target/connection
diff --git a/test/integration/targets/connection_local/runme.sh b/test/integration/targets/connection_local/runme.sh
new file mode 100755
index 0000000..a2c32ad
--- /dev/null
+++ b/test/integration/targets/connection_local/runme.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -eux
+
+group=local
+
+cd ../connection
+
+INVENTORY="../connection_${group}/test_connection.inventory" ./test.sh \
+ -e target_hosts="${group}" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
diff --git a/test/integration/targets/connection_local/test_connection.inventory b/test/integration/targets/connection_local/test_connection.inventory
new file mode 100644
index 0000000..64a2722
--- /dev/null
+++ b/test/integration/targets/connection_local/test_connection.inventory
@@ -0,0 +1,7 @@
+[local]
+local-pipelining ansible_ssh_pipelining=true
+local-no-pipelining ansible_ssh_pipelining=false
+[local:vars]
+ansible_host=localhost
+ansible_connection=local
+ansible_python_interpreter="{{ ansible_playbook_python }}"
diff --git a/test/integration/targets/connection_paramiko_ssh/aliases b/test/integration/targets/connection_paramiko_ssh/aliases
new file mode 100644
index 0000000..3851c95
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/aliases
@@ -0,0 +1,5 @@
+needs/ssh
+shippable/posix/group5
+needs/target/setup_paramiko
+needs/target/connection
+destructive # potentially installs/uninstalls OS packages via setup_paramiko
diff --git a/test/integration/targets/connection_paramiko_ssh/runme.sh b/test/integration/targets/connection_paramiko_ssh/runme.sh
new file mode 100755
index 0000000..123f6e2
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/runme.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -eux
+
+source ../setup_paramiko/setup.sh
+
+./test.sh
diff --git a/test/integration/targets/connection_paramiko_ssh/test.sh b/test/integration/targets/connection_paramiko_ssh/test.sh
new file mode 100755
index 0000000..de1ae67
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/test.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -eux
+
+group=paramiko_ssh
+
+cd ../connection
+
+INVENTORY="../connection_${group}/test_connection.inventory" ./test.sh \
+ -e target_hosts="${group}" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
diff --git a/test/integration/targets/connection_paramiko_ssh/test_connection.inventory b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
new file mode 100644
index 0000000..a3f34ab
--- /dev/null
+++ b/test/integration/targets/connection_paramiko_ssh/test_connection.inventory
@@ -0,0 +1,7 @@
+[paramiko_ssh]
+paramiko_ssh-pipelining ansible_ssh_pipelining=true
+paramiko_ssh-no-pipelining ansible_ssh_pipelining=false
+[paramiko_ssh:vars]
+ansible_host=localhost
+ansible_connection=paramiko_ssh
+ansible_python_interpreter="{{ ansible_playbook_python }}"
diff --git a/test/integration/targets/connection_psrp/aliases b/test/integration/targets/connection_psrp/aliases
new file mode 100644
index 0000000..b3e9b8b
--- /dev/null
+++ b/test/integration/targets/connection_psrp/aliases
@@ -0,0 +1,4 @@
+windows
+shippable/windows/group1
+shippable/windows/smoketest
+needs/target/connection
diff --git a/test/integration/targets/connection_psrp/files/empty.txt b/test/integration/targets/connection_psrp/files/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/integration/targets/connection_psrp/files/empty.txt
diff --git a/test/integration/targets/connection_psrp/runme.sh b/test/integration/targets/connection_psrp/runme.sh
new file mode 100755
index 0000000..35984bb
--- /dev/null
+++ b/test/integration/targets/connection_psrp/runme.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# make sure hosts are using psrp connections
+ansible -i ../../inventory.winrm localhost \
+ -m template \
+ -a "src=test_connection.inventory.j2 dest=${OUTPUT_DIR}/test_connection.inventory" \
+ "$@"
+
+python.py -m pip install pypsrp
+cd ../connection
+
+INVENTORY="${OUTPUT_DIR}/test_connection.inventory" ./test.sh \
+ -e target_hosts=windows \
+ -e action_prefix=win_ \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=c:/windows/temp/ansible-remote \
+ "$@"
+
+cd ../connection_psrp
+
+ansible-playbook -i "${OUTPUT_DIR}/test_connection.inventory" tests.yml \
+ "$@"
diff --git a/test/integration/targets/connection_psrp/test_connection.inventory.j2 b/test/integration/targets/connection_psrp/test_connection.inventory.j2
new file mode 100644
index 0000000..d2d3a49
--- /dev/null
+++ b/test/integration/targets/connection_psrp/test_connection.inventory.j2
@@ -0,0 +1,9 @@
+[windows]
+{% for host in vars.groups.windows %}
+{{ host }} ansible_host={{ hostvars[host]['ansible_host'] }} ansible_port={{ hostvars[host]['ansible_port'] }} ansible_user={{ hostvars[host]['ansible_user'] }} ansible_password={{ hostvars[host]['ansible_password'] }}
+{% endfor %}
+
+[windows:vars]
+ansible_connection=psrp
+ansible_psrp_auth=negotiate
+ansible_psrp_cert_validation=ignore
diff --git a/test/integration/targets/connection_psrp/tests.yml b/test/integration/targets/connection_psrp/tests.yml
new file mode 100644
index 0000000..dabbf40
--- /dev/null
+++ b/test/integration/targets/connection_psrp/tests.yml
@@ -0,0 +1,133 @@
+---
+# these are extra tests for psrp that aren't covered under test/integration/targets/connection/*
+- name: test out psrp specific tests
+ hosts: windows
+ serial: 1
+ gather_facts: no
+
+ tasks:
+ - name: test complex objects in raw output
+ # until PyYAML is upgraded to 4.x we need to use the \U escape for a unicode codepoint
+ # and enclose in a quote to it translates the \U
+ raw: "
+ [PSCustomObject]@{string = 'string'};
+ [PSCustomObject]@{unicode = 'poo - \U0001F4A9'};
+ [PSCustomObject]@{integer = 1};
+ [PSCustomObject]@{list = @(1, 2)};
+ Get-Service -Name winrm;
+ Write-Output -InputObject 'string - \U0001F4A9';"
+ register: raw_out
+
+ - name: assert complex objects in raw output
+ assert:
+ that:
+ - raw_out.stdout_lines|count == 6
+ - "raw_out.stdout_lines[0] == 'string: string'"
+ - "raw_out.stdout_lines[1] == 'unicode: poo - \U0001F4A9'"
+ - "raw_out.stdout_lines[2] == 'integer: 1'"
+ - "raw_out.stdout_lines[3] == \"list: [1, 2]\""
+ - raw_out.stdout_lines[4] == "winrm"
+ - raw_out.stdout_lines[5] == "string - \U0001F4A9"
+
+ # Become only works on Server 2008 when running with basic auth, skip this host for now as it is too complicated to
+ # override the auth protocol in the tests.
+ - name: check if we running on Server 2008
+ win_shell: '[System.Environment]::OSVersion.Version -ge [Version]"6.1"'
+ register: os_version
+
+ - name: test out become with psrp
+ win_whoami:
+ when: os_version|bool
+ register: whoami_out
+ become: yes
+ become_method: runas
+ become_user: SYSTEM
+
+ - name: assert test out become with psrp
+ assert:
+ that:
+ - whoami_out.account.sid == "S-1-5-18"
+ when: os_version|bool
+
+ - name: test out async with psrp
+ win_shell: Start-Sleep -Seconds 2; Write-Output abc
+ async: 10
+ poll: 1
+ register: async_out
+
+ - name: assert est out async with psrp
+ assert:
+ that:
+ - async_out.stdout_lines == ["abc"]
+
+ - name: Output unicode characters from Powershell using PSRP
+ win_command: "powershell.exe -ExecutionPolicy ByPass -Command \"Write-Host '\U0001F4A9'\""
+ register: command_unicode_output
+
+ - name: Assert unicode output
+ assert:
+ that:
+ - command_unicode_output is changed
+ - command_unicode_output.rc == 0
+ - "command_unicode_output.stdout == '\U0001F4A9\n'"
+ - command_unicode_output.stderr == ''
+
+ - name: Output unicode characters from Powershell using PSRP
+ win_shell: "Write-Host '\U0001F4A9'"
+ register: shell_unicode_output
+
+ - name: Assert unicode output
+ assert:
+ that:
+ - shell_unicode_output is changed
+ - shell_unicode_output.rc == 0
+ - "shell_unicode_output.stdout == '\U0001F4A9\n'"
+ - shell_unicode_output.stderr == ''
+
+ - name: copy empty file
+ win_copy:
+ src: empty.txt
+ dest: C:\Windows\TEMP\empty.txt
+ register: copy_empty
+
+ - name: get result of copy empty file
+ win_stat:
+ path: C:\Windows\TEMP\empty.txt
+ get_checksum: yes
+ register: copy_empty_actual
+
+ - name: assert copy empty file
+ assert:
+ that:
+ - copy_empty.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+ - copy_empty_actual.stat.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+ - copy_empty_actual.stat.size == 0
+
+ - block:
+ - name: fetch empty file
+ fetch:
+ src: C:\Windows\TEMP\empty.txt
+ dest: /tmp/empty.txt
+ flat: yes
+ register: fetch_empty
+
+ - name: get result of fetch empty file
+ stat:
+ path: /tmp/empty.txt
+ get_checksum: yes
+ register: fetch_empty_actual
+ delegate_to: localhost
+
+ - name: assert fetch empty file
+ assert:
+ that:
+ - fetch_empty.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+ - fetch_empty_actual.stat.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
+ - fetch_empty_actual.stat.size == 0
+
+ always:
+ - name: remove tmp file
+ file:
+ path: /tmp/empty.txt
+ state: absent
+ delegate_to: localhost
diff --git a/test/integration/targets/connection_remote_is_local/aliases b/test/integration/targets/connection_remote_is_local/aliases
new file mode 100644
index 0000000..1d28bdb
--- /dev/null
+++ b/test/integration/targets/connection_remote_is_local/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group5
+context/controller
diff --git a/test/integration/targets/connection_remote_is_local/connection_plugins/remote_is_local.py b/test/integration/targets/connection_remote_is_local/connection_plugins/remote_is_local.py
new file mode 100644
index 0000000..818bca4
--- /dev/null
+++ b/test/integration/targets/connection_remote_is_local/connection_plugins/remote_is_local.py
@@ -0,0 +1,25 @@
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+DOCUMENTATION = '''
+ name: remote_is_local
+ short_description: remote is local
+ description:
+ - remote_is_local
+ author: ansible (@core)
+ version_added: historical
+ extends_documentation_fragment:
+ - connection_pipelining
+ notes:
+ - The remote user is ignored, the user with which the ansible CLI was executed is used instead.
+'''
+
+
+from ansible.plugins.connection.local import Connection as LocalConnection
+
+
+class Connection(LocalConnection):
+ _remote_is_local = True
diff --git a/test/integration/targets/connection_remote_is_local/tasks/main.yml b/test/integration/targets/connection_remote_is_local/tasks/main.yml
new file mode 100644
index 0000000..265713a
--- /dev/null
+++ b/test/integration/targets/connection_remote_is_local/tasks/main.yml
@@ -0,0 +1,15 @@
+- command: ansible-playbook {{ role_path }}/test.yml -vvv -i {{ '-i '.join(ansible_inventory_sources) }}
+ environment:
+ ANSIBLE_REMOTE_TEMP: /i/dont/exist
+ ANSIBLE_NOCOLOR: 'true'
+ register: result
+
+- assert:
+ that:
+ - >-
+ result.stdout is search('PUT ' ~ ansible_local ~ ' TO ' ~ ansible_local)
+ - >-
+ '/i/dont/exist' not in result.stdout
+ vars:
+ local_tmp: '{{ q("config", "remote_tmp", plugin_type="shell", plugin_name="sh")|first|expanduser|realpath }}'
+ ansible_local: '{{ local_tmp }}/ansible-local-\S+'
diff --git a/test/integration/targets/connection_remote_is_local/test.yml b/test/integration/targets/connection_remote_is_local/test.yml
new file mode 100644
index 0000000..b76ba5f
--- /dev/null
+++ b/test/integration/targets/connection_remote_is_local/test.yml
@@ -0,0 +1,8 @@
+- hosts: testhost
+ gather_facts: false
+ tasks:
+ - ping:
+ vars:
+ ansible_connection: remote_is_local
+ ansible_pipelining: false
+ ansible_remote_tmp: /i/dont/exist
diff --git a/test/integration/targets/connection_ssh/aliases b/test/integration/targets/connection_ssh/aliases
new file mode 100644
index 0000000..bd04bed
--- /dev/null
+++ b/test/integration/targets/connection_ssh/aliases
@@ -0,0 +1,3 @@
+needs/ssh
+shippable/posix/group3
+needs/target/connection
diff --git a/test/integration/targets/connection_ssh/check_ssh_defaults.yml b/test/integration/targets/connection_ssh/check_ssh_defaults.yml
new file mode 100644
index 0000000..937f1f7
--- /dev/null
+++ b/test/integration/targets/connection_ssh/check_ssh_defaults.yml
@@ -0,0 +1,29 @@
+- hosts: ssh
+ gather_facts: false
+ vars:
+ ansible_connection: ssh
+ ansible_ssh_timeout: 10
+ tasks:
+ - name: contain the maddness
+ block:
+ - name: test all is good
+ ping:
+
+ - name: start the fun
+ meta: reset_connection
+
+ - name: now test we can use wrong port from ssh/config
+ ping:
+ ignore_unreachable: True
+ vars:
+ ansible_ssh_args: "-F {{playbook_dir}}/files/port_overrride_ssh.cfg"
+ register: expected
+
+ - name: check all is as expected
+ assert:
+ that:
+ - expected['unreachable']|bool
+ - "'2222' in expected['msg']"
+ always:
+ - name: make sure we don't cache the bad connection
+ meta: reset_connection
diff --git a/test/integration/targets/connection_ssh/files/port_overrride_ssh.cfg b/test/integration/targets/connection_ssh/files/port_overrride_ssh.cfg
new file mode 100644
index 0000000..7f8422e
--- /dev/null
+++ b/test/integration/targets/connection_ssh/files/port_overrride_ssh.cfg
@@ -0,0 +1,2 @@
+Host *
+ Port 2222
diff --git a/test/integration/targets/connection_ssh/posix.sh b/test/integration/targets/connection_ssh/posix.sh
new file mode 100755
index 0000000..8f036fb
--- /dev/null
+++ b/test/integration/targets/connection_ssh/posix.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -eux
+
+group=ssh
+
+cd ../connection
+
+INVENTORY="../connection_${group}/test_connection.inventory" ./test.sh \
+ -e target_hosts="${group}" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
diff --git a/test/integration/targets/connection_ssh/runme.sh b/test/integration/targets/connection_ssh/runme.sh
new file mode 100755
index 0000000..ad817c8
--- /dev/null
+++ b/test/integration/targets/connection_ssh/runme.sh
@@ -0,0 +1,81 @@
+#!/usr/bin/env bash
+
+set -ux
+
+# We skip this whole section if the test node doesn't have sshpass on it.
+if command -v sshpass > /dev/null; then
+ # Check if our sshpass supports -P
+ sshpass -P foo > /dev/null
+ sshpass_supports_prompt=$?
+ if [[ $sshpass_supports_prompt -eq 0 ]]; then
+ # If the prompt is wrong, we'll end up hanging (due to sshpass hanging).
+ # We should probably do something better here, like timing out in Ansible,
+ # but this has been the behavior for a long time, before we supported custom
+ # password prompts.
+ #
+ # So we search for a custom password prompt that is clearly wrong and call
+ # ansible with timeout. If we time out, our custom prompt was successfully
+ # searched for. It's a weird way of doing things, but it does ensure
+ # that the flag gets passed to sshpass.
+ timeout 5 ansible -m ping \
+ -e ansible_connection=ssh \
+ -e ansible_sshpass_prompt=notThis: \
+ -e ansible_password=foo \
+ -e ansible_user=definitelynotroot \
+ -i test_connection.inventory \
+ ssh-pipelining
+ ret=$?
+ # 124 is EXIT_TIMEDOUT from gnu coreutils
+ # 143 is 128+SIGTERM(15) from BusyBox
+ if [[ $ret -ne 124 && $ret -ne 143 ]]; then
+ echo "Expected to time out and we did not. Exiting with failure."
+ exit 1
+ fi
+ else
+ ansible -m ping \
+ -e ansible_connection=ssh \
+ -e ansible_sshpass_prompt=notThis: \
+ -e ansible_password=foo \
+ -e ansible_user=definitelynotroot \
+ -i test_connection.inventory \
+ ssh-pipelining | grep 'customized password prompts'
+ ret=$?
+ [[ $ret -eq 0 ]] || exit $ret
+ fi
+fi
+
+set -e
+
+if [[ "$(scp -O 2>&1)" == "usage: scp "* ]]; then
+ # scp supports the -O option (and thus the -T option as well)
+ # work-around required
+ # see: https://www.openssh.com/txt/release-9.0
+ scp_args=("-e" "ansible_scp_extra_args=-TO")
+elif [[ "$(scp -T 2>&1)" == "usage: scp "* ]]; then
+ # scp supports the -T option
+ # work-around required
+ # see: https://github.com/ansible/ansible/issues/52640
+ scp_args=("-e" "ansible_scp_extra_args=-T")
+else
+ # scp does not support the -T or -O options
+ # no work-around required
+ # however we need to put something in the array to keep older versions of bash happy
+ scp_args=("-e" "")
+fi
+
+# sftp
+./posix.sh "$@"
+# scp
+ANSIBLE_SCP_IF_SSH=true ./posix.sh "$@" "${scp_args[@]}"
+# piped
+ANSIBLE_SSH_TRANSFER_METHOD=piped ./posix.sh "$@"
+
+# test config defaults override
+ansible-playbook check_ssh_defaults.yml "$@" -i test_connection.inventory
+
+# ensure we can load from ini cfg
+ANSIBLE_CONFIG=./test_ssh_defaults.cfg ansible-playbook verify_config.yml "$@"
+
+# ensure we handle cp with spaces correctly, otherwise would fail with
+# `"Failed to connect to the host via ssh: command-line line 0: keyword controlpath extra arguments at end of line"`
+ANSIBLE_SSH_CONTROL_PATH='/tmp/ssh cp with spaces' ansible -m ping all -e ansible_connection=ssh -i test_connection.inventory "$@"
diff --git a/test/integration/targets/connection_ssh/test_connection.inventory b/test/integration/targets/connection_ssh/test_connection.inventory
new file mode 100644
index 0000000..a1a4ff1
--- /dev/null
+++ b/test/integration/targets/connection_ssh/test_connection.inventory
@@ -0,0 +1,7 @@
+[ssh]
+ssh-pipelining ansible_ssh_pipelining=true
+ssh-no-pipelining ansible_ssh_pipelining=false
+[ssh:vars]
+ansible_host=localhost
+ansible_connection=ssh
+ansible_python_interpreter="{{ ansible_playbook_python }}"
diff --git a/test/integration/targets/connection_ssh/test_ssh_defaults.cfg b/test/integration/targets/connection_ssh/test_ssh_defaults.cfg
new file mode 100644
index 0000000..362f946
--- /dev/null
+++ b/test/integration/targets/connection_ssh/test_ssh_defaults.cfg
@@ -0,0 +1,5 @@
+[ssh_connection]
+ssh_common_args=fromconfig
+ssh_extra_args=fromconfig
+scp_extra_args=fromconfig
+sftp_extra_args=fromconfig
diff --git a/test/integration/targets/connection_ssh/verify_config.yml b/test/integration/targets/connection_ssh/verify_config.yml
new file mode 100644
index 0000000..0bf7958
--- /dev/null
+++ b/test/integration/targets/connection_ssh/verify_config.yml
@@ -0,0 +1,21 @@
+- hosts: localhost
+ gather_facts: false
+ vars:
+ ssh_configs:
+ - ssh_common_args
+ - ssh_extra_args
+ - sftp_extra_args
+ - scp_extra_args
+ tasks:
+ - debug:
+ msg: '{{item ~ ": " ~ lookup("config", item, plugin_type="connection", plugin_name="ssh")}}'
+ verbosity: 3
+ loop: '{{ssh_configs}}'
+ tags: [ configfile ]
+
+ - name: check config from file
+ assert:
+ that:
+ - 'lookup("config", item, plugin_type="connection", plugin_name="ssh") == "fromconfig"'
+ loop: '{{ssh_configs}}'
+ tags: [ configfile ]
diff --git a/test/integration/targets/connection_windows_ssh/aliases b/test/integration/targets/connection_windows_ssh/aliases
new file mode 100644
index 0000000..af3f193
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/aliases
@@ -0,0 +1,5 @@
+windows
+shippable/windows/group1
+shippable/windows/smoketest
+needs/target/connection
+needs/target/setup_remote_tmp_dir
diff --git a/test/integration/targets/connection_windows_ssh/runme.sh b/test/integration/targets/connection_windows_ssh/runme.sh
new file mode 100755
index 0000000..766193f
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/runme.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# We need to run these tests with both the powershell and cmd shell type
+
+### cmd tests - no DefaultShell set ###
+ansible -i ../../inventory.winrm localhost \
+ -m template \
+ -a "src=test_connection.inventory.j2 dest=${OUTPUT_DIR}/test_connection.inventory" \
+ -e "test_shell_type=cmd" \
+ "$@"
+
+# https://github.com/PowerShell/Win32-OpenSSH/wiki/DefaultShell
+ansible -i ../../inventory.winrm windows \
+ -m win_regedit \
+ -a "path=HKLM:\\\\SOFTWARE\\\\OpenSSH name=DefaultShell state=absent" \
+ "$@"
+
+# Need to flush the connection to ensure we get a new shell for the next tests
+ansible -i "${OUTPUT_DIR}/test_connection.inventory" windows \
+ -m meta -a "reset_connection" \
+ "$@"
+
+# sftp
+./windows.sh "$@"
+# scp
+ANSIBLE_SSH_TRANSFER_METHOD=scp ./windows.sh "$@"
+# other tests not part of the generic connection test framework
+ansible-playbook -i "${OUTPUT_DIR}/test_connection.inventory" tests.yml \
+ "$@"
+
+### powershell tests - explicit DefaultShell set ###
+# we do this last as the default shell on our CI instances is set to PowerShell
+ansible -i ../../inventory.winrm localhost \
+ -m template \
+ -a "src=test_connection.inventory.j2 dest=${OUTPUT_DIR}/test_connection.inventory" \
+ -e "test_shell_type=powershell" \
+ "$@"
+
+# ensure the default shell is set to PowerShell
+ansible -i ../../inventory.winrm windows \
+ -m win_regedit \
+ -a "path=HKLM:\\\\SOFTWARE\\\\OpenSSH name=DefaultShell data=C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe" \
+ "$@"
+
+ansible -i "${OUTPUT_DIR}/test_connection.inventory" windows \
+ -m meta -a "reset_connection" \
+ "$@"
+
+./windows.sh "$@"
+ANSIBLE_SSH_TRANSFER_METHOD=scp ./windows.sh "$@"
+ansible-playbook -i "${OUTPUT_DIR}/test_connection.inventory" tests.yml \
+ "$@"
diff --git a/test/integration/targets/connection_windows_ssh/test_connection.inventory.j2 b/test/integration/targets/connection_windows_ssh/test_connection.inventory.j2
new file mode 100644
index 0000000..5893eaf
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/test_connection.inventory.j2
@@ -0,0 +1,12 @@
+[windows]
+{% for host in vars.groups.windows %}
+{{ host }} ansible_host={{ hostvars[host]['ansible_host'] }} ansible_user={{ hostvars[host]['ansible_user'] }}{{ ' ansible_ssh_private_key_file=' ~ hostvars[host]['ansible_ssh_private_key_file'] if (hostvars[host]['ansible_ssh_private_key_file']|default()) else '' }}
+{% endfor %}
+
+[windows:vars]
+ansible_shell_type={{ test_shell_type }}
+ansible_connection=ssh
+ansible_port=22
+# used to preserve the existing environment and not touch existing files
+ansible_ssh_extra_args="-o UserKnownHostsFile=/dev/null"
+ansible_ssh_host_key_checking=False
diff --git a/test/integration/targets/connection_windows_ssh/tests.yml b/test/integration/targets/connection_windows_ssh/tests.yml
new file mode 100644
index 0000000..e9b538b
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/tests.yml
@@ -0,0 +1,32 @@
+---
+- name: test out Windows SSH specific tests
+ hosts: windows
+ serial: 1
+ gather_facts: no
+
+ tasks:
+ - name: test out become with Windows SSH
+ win_whoami:
+ register: win_ssh_become
+ become: yes
+ become_method: runas
+ become_user: SYSTEM
+
+ - name: assert test out become with Windows SSH
+ assert:
+ that:
+ - win_ssh_become.account.sid == "S-1-5-18"
+
+ - name: test out async with Windows SSH
+ win_shell: Write-Host café
+ async: 20
+ poll: 3
+ register: win_ssh_async
+
+ - name: assert test out async with Windows SSH
+ assert:
+ that:
+ - win_ssh_async is changed
+ - win_ssh_async.rc == 0
+ - win_ssh_async.stdout == "café\n"
+ - win_ssh_async.stderr == ""
diff --git a/test/integration/targets/connection_windows_ssh/tests_fetch.yml b/test/integration/targets/connection_windows_ssh/tests_fetch.yml
new file mode 100644
index 0000000..0b4fe94
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/tests_fetch.yml
@@ -0,0 +1,41 @@
+# This must be a play as we need to invoke it with the ANSIBLE_SCP_IF_SSH env
+# to control the mechanism used. Unfortunately while ansible_scp_if_ssh is
+# documented, it isn't actually used hence the separate invocation
+---
+- name: further fetch tests with metachar characters in filename
+ hosts: windows
+ force_handlers: yes
+ serial: 1
+ gather_facts: no
+
+ tasks:
+ - name: setup remote tmp dir
+ import_role:
+ name: ../../setup_remote_tmp_dir
+
+ - name: create remote file with metachar in name
+ win_copy:
+ content: some content
+ dest: '{{ remote_tmp_dir }}\file ^with &whoami'
+
+ - name: test fetch against a file with cmd metacharacters
+ block:
+ - name: fetch file with metachar in name
+ fetch:
+ src: '{{ remote_tmp_dir }}\file ^with &whoami'
+ dest: ansible-test.txt
+ flat: yes
+ register: fetch_res
+
+ - name: assert fetch file with metachar in name
+ assert:
+ that:
+ - fetch_res is changed
+ - fetch_res.checksum == '94e66df8cd09d410c62d9e0dc59d3a884e458e05'
+
+ always:
+ - name: remove local copy of file
+ file:
+ path: ansible-test.txt
+ state: absent
+ delegate_to: localhost
diff --git a/test/integration/targets/connection_windows_ssh/windows.sh b/test/integration/targets/connection_windows_ssh/windows.sh
new file mode 100755
index 0000000..d2db50f
--- /dev/null
+++ b/test/integration/targets/connection_windows_ssh/windows.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -eux
+
+cd ../connection
+
+# A recent patch to OpenSSH causes a validation error when running through Ansible. It seems like if the path is quoted
+# then it will fail with 'protocol error: filename does not match request'. We currently ignore this by setting
+# 'ansible_scp_extra_args=-T' to ignore this check but this should be removed once that bug is fixed and our test
+# container has been updated.
+# https://unix.stackexchange.com/questions/499958/why-does-scps-strict-filename-checking-reject-quoted-last-component-but-not-oth
+# https://github.com/openssh/openssh-portable/commit/391ffc4b9d31fa1f4ad566499fef9176ff8a07dc
+INVENTORY="${OUTPUT_DIR}/test_connection.inventory" ./test.sh \
+ -e target_hosts=windows \
+ -e action_prefix=win_ \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=c:/windows/temp/ansible-remote \
+ -e ansible_scp_extra_args=-T \
+ "$@"
+
+cd ../connection_windows_ssh
+
+ansible-playbook -i "${OUTPUT_DIR}/test_connection.inventory" tests_fetch.yml \
+ -e ansible_scp_extra_args=-T \
+ "$@"
diff --git a/test/integration/targets/connection_winrm/aliases b/test/integration/targets/connection_winrm/aliases
new file mode 100644
index 0000000..af3f193
--- /dev/null
+++ b/test/integration/targets/connection_winrm/aliases
@@ -0,0 +1,5 @@
+windows
+shippable/windows/group1
+shippable/windows/smoketest
+needs/target/connection
+needs/target/setup_remote_tmp_dir
diff --git a/test/integration/targets/connection_winrm/runme.sh b/test/integration/targets/connection_winrm/runme.sh
new file mode 100755
index 0000000..36a7aa8
--- /dev/null
+++ b/test/integration/targets/connection_winrm/runme.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# make sure hosts are using winrm connections
+ansible -i ../../inventory.winrm localhost \
+ -m template \
+ -a "src=test_connection.inventory.j2 dest=${OUTPUT_DIR}/test_connection.inventory" \
+ "$@"
+
+cd ../connection
+
+INVENTORY="${OUTPUT_DIR}/test_connection.inventory" ./test.sh \
+ -e target_hosts=windows \
+ -e action_prefix=win_ \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=c:/windows/temp/ansible-remote \
+ "$@"
+
+cd ../connection_winrm
+
+ansible-playbook -i "${OUTPUT_DIR}/test_connection.inventory" tests.yml \
+ "$@"
diff --git a/test/integration/targets/connection_winrm/test_connection.inventory.j2 b/test/integration/targets/connection_winrm/test_connection.inventory.j2
new file mode 100644
index 0000000..7c4f3dc
--- /dev/null
+++ b/test/integration/targets/connection_winrm/test_connection.inventory.j2
@@ -0,0 +1,10 @@
+[windows]
+{% for host in vars.groups.windows %}
+{{ host }} ansible_host={{ hostvars[host]['ansible_host'] }} ansible_port={{ hostvars[host]['ansible_port'] }} ansible_user={{ hostvars[host]['ansible_user'] }} ansible_password={{ hostvars[host]['ansible_password'] }}
+{% endfor %}
+
+[windows:vars]
+ansible_connection=winrm
+# we don't know if we're using an encrypted connection or not, so we'll use message encryption
+ansible_winrm_transport=ntlm
+ansible_winrm_server_cert_validation=ignore
diff --git a/test/integration/targets/connection_winrm/tests.yml b/test/integration/targets/connection_winrm/tests.yml
new file mode 100644
index 0000000..78f92a4
--- /dev/null
+++ b/test/integration/targets/connection_winrm/tests.yml
@@ -0,0 +1,28 @@
+---
+- name: test out Windows WinRM specific tests
+ hosts: windows
+ force_handlers: yes
+ serial: 1
+ gather_facts: no
+
+ tasks:
+ - name: setup remote tmp dir
+ import_role:
+ name: ../../setup_remote_tmp_dir
+
+ - name: copy across empty file
+ win_copy:
+ content: ''
+ dest: '{{ remote_tmp_dir }}\empty.txt'
+ register: winrm_copy_empty
+
+ - name: get result of copy across empty file
+ win_stat:
+ path: '{{ remote_tmp_dir }}\empty.txt'
+ register: winrm_copy_empty_actual
+
+ - name: assert copy across empty file
+ assert:
+ that:
+ - winrm_copy_empty is changed
+ - winrm_copy_empty_actual.stat.size == 0