From e6e98407178556c1eb60101abef1df08c753d31d Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Thu, 17 Sep 2020 16:57:28 -0500 Subject: [PATCH] Remove incidentals without coverage (#71788) * Remove incidental_lookup_hashi_vault * Remove incidental_connection_chroot * Remove incidental_selinux * Remove incidental_win_hosts --- .../incidental_connection_chroot/aliases | 3 - .../incidental_connection_chroot/runme.sh | 18 - .../test_connection.inventory | 7 - .../incidental_lookup_hashi_vault/aliases | 7 - .../lookup_hashi_vault/defaults/main.yml | 4 - .../tasks/approle_setup.yml | 21 - .../lookup_hashi_vault/tasks/approle_test.yml | 45 --- .../lookup_hashi_vault/tasks/main.yml | 155 -------- .../lookup_hashi_vault/tasks/tests.yml | 35 -- .../lookup_hashi_vault/tasks/token_setup.yml | 3 - .../lookup_hashi_vault/tasks/token_test.yml | 58 --- .../templates/vault_config.hcl.j2 | 10 - .../playbooks/install_dependencies.yml | 19 - .../playbooks/test_lookup_hashi_vault.yml | 9 - .../incidental_lookup_hashi_vault/runme.sh | 23 -- .../targets/incidental_selinux/aliases | 3 - .../targets/incidental_selinux/tasks/main.yml | 36 -- .../incidental_selinux/tasks/selinux.yml | 364 ------------------ .../incidental_selinux/tasks/selogin.yml | 81 ---- .../targets/incidental_win_hosts/aliases | 2 - .../incidental_win_hosts/defaults/main.yml | 13 - .../incidental_win_hosts/meta/main.yml | 2 - .../incidental_win_hosts/tasks/main.yml | 17 - .../incidental_win_hosts/tasks/tests.yml | 189 --------- .../integration/plugins/connection/chroot.py | 208 ---------- .../integration/plugins/lookup/hashi_vault.py | 302 --------------- .../integration/plugins/modules/selinux.py | 266 ------------- .../plugins/modules/win_hosts.ps1 | 257 ------------- .../plugins/modules/win_hosts.py | 126 ------ 29 files changed, 2283 deletions(-) delete mode 100644 test/integration/targets/incidental_connection_chroot/aliases delete mode 100755 test/integration/targets/incidental_connection_chroot/runme.sh delete mode 100644 test/integration/targets/incidental_connection_chroot/test_connection.inventory delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/aliases delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/playbooks/install_dependencies.yml delete mode 100644 test/integration/targets/incidental_lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml delete mode 100755 test/integration/targets/incidental_lookup_hashi_vault/runme.sh delete mode 100644 test/integration/targets/incidental_selinux/aliases delete mode 100644 test/integration/targets/incidental_selinux/tasks/main.yml delete mode 100644 test/integration/targets/incidental_selinux/tasks/selinux.yml delete mode 100644 test/integration/targets/incidental_selinux/tasks/selogin.yml delete mode 100644 test/integration/targets/incidental_win_hosts/aliases delete mode 100644 test/integration/targets/incidental_win_hosts/defaults/main.yml delete mode 100644 test/integration/targets/incidental_win_hosts/meta/main.yml delete mode 100644 test/integration/targets/incidental_win_hosts/tasks/main.yml delete mode 100644 test/integration/targets/incidental_win_hosts/tasks/tests.yml delete mode 100644 test/support/integration/plugins/connection/chroot.py delete mode 100644 test/support/integration/plugins/lookup/hashi_vault.py delete mode 100644 test/support/integration/plugins/modules/selinux.py delete mode 100644 test/support/windows-integration/plugins/modules/win_hosts.ps1 delete mode 100644 test/support/windows-integration/plugins/modules/win_hosts.py diff --git a/test/integration/targets/incidental_connection_chroot/aliases b/test/integration/targets/incidental_connection_chroot/aliases deleted file mode 100644 index 01f0bd4e610..00000000000 --- a/test/integration/targets/incidental_connection_chroot/aliases +++ /dev/null @@ -1,3 +0,0 @@ -needs/root -shippable/posix/incidental -needs/target/connection diff --git a/test/integration/targets/incidental_connection_chroot/runme.sh b/test/integration/targets/incidental_connection_chroot/runme.sh deleted file mode 100755 index e7eb01d3c7b..00000000000 --- a/test/integration/targets/incidental_connection_chroot/runme.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -# Connection tests for POSIX platforms use this script by linking to it from the appropriate 'connection_' target dir. -# The name of the inventory group to test is extracted from the directory name following the 'connection_' prefix. - -group=$(python -c \ - "from os import path; print(path.basename(path.abspath(path.dirname('$0'))).replace('incidental_connection_', ''))") - -cd ../connection - -INVENTORY="../incidental_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/incidental_connection_chroot/test_connection.inventory b/test/integration/targets/incidental_connection_chroot/test_connection.inventory deleted file mode 100644 index 5f78393f212..00000000000 --- a/test/integration/targets/incidental_connection_chroot/test_connection.inventory +++ /dev/null @@ -1,7 +0,0 @@ -[chroot] -chroot-pipelining ansible_ssh_pipelining=true -chroot-no-pipelining ansible_ssh_pipelining=false -[chroot:vars] -ansible_host=/ -ansible_connection=chroot -ansible_python_interpreter="{{ ansible_playbook_python }}" diff --git a/test/integration/targets/incidental_lookup_hashi_vault/aliases b/test/integration/targets/incidental_lookup_hashi_vault/aliases deleted file mode 100644 index 3dded09a498..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/aliases +++ /dev/null @@ -1,7 +0,0 @@ -shippable/posix/incidental -destructive -needs/target/incidental_setup_openssl -needs/file/test/lib/ansible_test/_data/requirements/constraints.txt -skip/aix -skip/power/centos -skip/python2.6 diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml deleted file mode 100644 index f1f6dd981d4..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -vault_gen_path: 'gen/testproject' -vault_kv1_path: 'kv1/testproject' -vault_kv2_path: 'kv2/data/testproject' diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml deleted file mode 100644 index 63307728a38..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml +++ /dev/null @@ -1,21 +0,0 @@ -- name: 'Create an approle policy' - shell: "echo '{{ policy }}' | {{ vault_cmd }} policy write approle-policy -" - vars: - policy: | - path "auth/approle/login" { - capabilities = [ "create", "read" ] - } - -- name: 'Enable the AppRole auth method' - command: '{{ vault_cmd }} auth enable approle' - -- name: 'Create a named role' - command: '{{ vault_cmd }} write auth/approle/role/test-role policies="test-policy,approle-policy"' - -- name: 'Fetch the RoleID of the AppRole' - command: '{{ vault_cmd }} read -field=role_id auth/approle/role/test-role/role-id' - register: role_id_cmd - -- name: 'Get a SecretID issued against the AppRole' - command: '{{ vault_cmd }} write -field=secret_id -f auth/approle/role/test-role/secret-id' - register: secret_id_cmd diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml deleted file mode 100644 index 44eb5ed18d4..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml +++ /dev/null @@ -1,45 +0,0 @@ -- vars: - role_id: '{{ role_id_cmd.stdout }}' - secret_id: '{{ secret_id_cmd.stdout }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - secret1: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - secret2: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - - - name: 'Check secret values' - fail: - msg: 'unexpected secret values' - when: secret1['value'] != 'foo1' or secret2['value'] != 'foo2' - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle secret_id=toto role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when inexistent secret is read' - vars: - secret_inexistent: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret4 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml deleted file mode 100644 index 42fd0907f3d..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml +++ /dev/null @@ -1,155 +0,0 @@ ---- -- name: Install Hashi Vault on controlled node and test - - vars: - vault_version: '0.11.0' - vault_uri: 'https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/lookup_hashi_vault/vault_{{ vault_version }}_{{ ansible_system | lower }}_{{ vault_arch }}.zip' - vault_cmd: '{{ local_temp_dir }}/vault' - - block: - - name: Create a local temporary directory - tempfile: - state: directory - register: tempfile_result - - - set_fact: - local_temp_dir: '{{ tempfile_result.path }}' - - - when: pyopenssl_version.stdout is version('0.15', '>=') - block: - - name: Generate privatekey - openssl_privatekey: - path: '{{ local_temp_dir }}/privatekey.pem' - - - name: Generate CSR - openssl_csr: - path: '{{ local_temp_dir }}/csr.csr' - privatekey_path: '{{ local_temp_dir }}/privatekey.pem' - subject: - commonName: localhost - - - name: Generate selfsigned certificate - openssl_certificate: - path: '{{ local_temp_dir }}/cert.pem' - csr_path: '{{ local_temp_dir }}/csr.csr' - privatekey_path: '{{ local_temp_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - register: selfsigned_certificate - - - name: 'Install unzip' - package: - name: unzip - when: ansible_distribution != "MacOSX" # unzip already installed - - - assert: - # Linux: x86_64, FreeBSD: amd64 - that: ansible_architecture in ['i386', 'x86_64', 'amd64'] - - set_fact: - vault_arch: '386' - when: ansible_architecture == 'i386' - - set_fact: - vault_arch: amd64 - when: ansible_architecture in ['x86_64', 'amd64'] - - - name: 'Download vault binary' - unarchive: - src: '{{ vault_uri }}' - dest: '{{ local_temp_dir }}' - remote_src: true - - - environment: - # used by vault command - VAULT_DEV_ROOT_TOKEN_ID: '47542cbc-6bf8-4fba-8eda-02e0a0d29a0a' - block: - - name: 'Create configuration file' - template: - src: vault_config.hcl.j2 - dest: '{{ local_temp_dir }}/vault_config.hcl' - - - name: 'Start vault service' - environment: - VAULT_ADDR: 'http://localhost:8200' - block: - - name: 'Start vault server (dev mode enabled)' - shell: 'nohup {{ vault_cmd }} server -dev -config {{ local_temp_dir }}/vault_config.hcl /dev/null 2>&1 &' - - - name: 'Create generic secrets engine' - command: '{{ vault_cmd }} secrets enable -path=gen generic' - - - name: 'Create KV v1 secrets engine' - command: '{{ vault_cmd }} secrets enable -path=kv1 -version=1 kv' - - - name: 'Create KV v2 secrets engine' - command: '{{ vault_cmd }} secrets enable -path=kv2 -version=2 kv' - - - name: 'Create a test policy' - shell: "echo '{{ policy }}' | {{ vault_cmd }} policy write test-policy -" - vars: - policy: | - path "{{ vault_gen_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_gen_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_gen_path }}/secret3" { - capabilities = ["deny"] - } - path "{{ vault_kv1_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_kv1_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_kv1_path }}/secret3" { - capabilities = ["deny"] - } - path "{{ vault_kv2_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_kv2_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_kv2_path }}/secret3" { - capabilities = ["deny"] - } - - - name: 'Create generic secrets' - command: '{{ vault_cmd }} write {{ vault_gen_path }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3] - - - name: 'Create KV v1 secrets' - command: '{{ vault_cmd }} kv put {{ vault_kv1_path }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3] - - - name: 'Create KV v2 secrets' - command: '{{ vault_cmd }} kv put {{ vault_kv2_path | regex_replace("/data") }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3] - - - name: setup approle auth - import_tasks: approle_setup.yml - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - name: setup token auth - import_tasks: token_setup.yml - - - import_tasks: tests.yml - vars: - auth_type: approle - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - import_tasks: tests.yml - vars: - auth_type: token - - always: - - name: 'Kill vault process' - shell: "kill $(cat {{ local_temp_dir }}/vault.pid)" - ignore_errors: true - - always: - - name: 'Delete temp dir' - file: - path: '{{ local_temp_dir }}' - state: absent diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml deleted file mode 100644 index 198f587a774..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml +++ /dev/null @@ -1,35 +0,0 @@ -- name: 'test {{ auth_type }} auth without SSL (lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=http://localhost:8200 ' - -- name: 'test {{ auth_type }} auth without SSL (environment variable)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'http://localhost:8200' - -- when: pyopenssl_version.stdout is version('0.15', '>=') - block: - - name: 'test {{ auth_type }} auth with certs (validation enabled, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=https://localhost:8201 ca_cert={{ local_temp_dir }}/cert.pem validate_certs=True ' - - - name: 'test {{ auth_type }} auth with certs (validation enabled, environment variables)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_CACERT: '{{ local_temp_dir }}/cert.pem' - - - name: 'test {{ auth_type }} auth with certs (validation disabled, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=https://localhost:8201 validate_certs=False ' diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml deleted file mode 100644 index d5ce2803462..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml +++ /dev/null @@ -1,3 +0,0 @@ -- name: 'Create a test credentials (token)' - command: '{{ vault_cmd }} token create -policy test-policy -field token' - register: user_token_cmd diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml deleted file mode 100644 index 20c1af791ee..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml +++ /dev/null @@ -1,58 +0,0 @@ -- vars: - user_token: '{{ user_token_cmd.stdout }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - gen_secret1: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_gen_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - gen_secret2: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_gen_path ~ '/secret2 token=' ~ user_token) }}" - kv1_secret1: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv1_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - kv1_secret2: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv1_path ~ '/secret2 token=' ~ user_token) }}" - kv2_secret1: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - kv2_secret2: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 token=' ~ user_token) }}" - - - name: 'Check secret generic values' - fail: - msg: 'unexpected secret values' - when: gen_secret1['value'] != 'foo1' or gen_secret2['value'] != 'foo2' - - - name: 'Check secret kv1 values' - fail: - msg: 'unexpected secret values' - when: kv1_secret1['value'] != 'foo1' or kv1_secret2['value'] != 'foo2' - - - name: 'Check secret kv2 values' - fail: - msg: 'unexpected secret values' - when: kv2_secret1['value'] != 'foo1' or kv2_secret2['value'] != 'foo2' - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=token token=wrong_token') }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 token=' ~ user_token) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when inexistent secret is read' - vars: - secret_inexistent: "{{ lookup('hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret4 token=' ~ user_token) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 b/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 deleted file mode 100644 index effc90ba903..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 +++ /dev/null @@ -1,10 +0,0 @@ -# {{ ansible_managed }} -pid_file = "{{ local_temp_dir }}/vault.pid" -{% if pyopenssl_version.stdout is version('0.15', '>=') %} -listener "tcp" { - tls_key_file = "{{ local_temp_dir }}/privatekey.pem" - tls_cert_file = "{{ local_temp_dir }}/cert.pem" - tls_disable = false - address = "localhost:8201" -} -{% endif %} diff --git a/test/integration/targets/incidental_lookup_hashi_vault/playbooks/install_dependencies.yml b/test/integration/targets/incidental_lookup_hashi_vault/playbooks/install_dependencies.yml deleted file mode 100644 index 9edbdbd6315..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/playbooks/install_dependencies.yml +++ /dev/null @@ -1,19 +0,0 @@ -- hosts: localhost - tasks: - - name: Install openssl - import_role: - name: incidental_setup_openssl - - - name: "RedHat <= 7, select last version compatible with request 2.6.0 (this version doesn't support approle auth)" - set_fact: - hvac_package: 'hvac==0.2.5' - when: ansible_distribution == 'RedHat' and ansible_distribution_major_version is version('7', '<=') - - - name: 'CentOS < 7, select last version compatible with Python 2.6' - set_fact: - hvac_package: 'hvac==0.5.0' - when: ansible_distribution == 'CentOS' and ansible_distribution_major_version is version('7', '<') - - - name: 'Install hvac Python package' - pip: - name: "{{ hvac_package|default('hvac') }}" diff --git a/test/integration/targets/incidental_lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml b/test/integration/targets/incidental_lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml deleted file mode 100644 index 343763af099..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml +++ /dev/null @@ -1,9 +0,0 @@ -- hosts: localhost - tasks: - - name: register pyOpenSSL version - command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'" - register: pyopenssl_version - - - name: Test lookup hashi_vault - import_role: - name: incidental_lookup_hashi_vault/lookup_hashi_vault diff --git a/test/integration/targets/incidental_lookup_hashi_vault/runme.sh b/test/integration/targets/incidental_lookup_hashi_vault/runme.sh deleted file mode 100755 index e5e0df347f8..00000000000 --- a/test/integration/targets/incidental_lookup_hashi_vault/runme.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -# First install pyOpenSSL, then test lookup in a second playbook in order to -# workaround this error which occurs on OS X 10.11 only: -# -# TASK [lookup_hashi_vault : test token auth with certs (validation enabled, lookup parameters)] *** -# included: lookup_hashi_vault/tasks/token_test.yml for testhost -# -# TASK [lookup_hashi_vault : Fetch secrets using "hashi_vault" lookup] *** -# From cffi callback : -# Traceback (most recent call last): -# File "/usr/local/lib/python2.7/site-packages/OpenSSL/SSL.py", line 309, in wrapper -# _lib.X509_up_ref(x509) -# AttributeError: 'module' object has no attribute 'X509_up_ref' -# fatal: [testhost]: FAILED! => { "msg": "An unhandled exception occurred while running the lookup plugin 'hashi_vault'. Error was a , original message: HTTPSConnectionPool(host='localhost', port=8201): Max retries exceeded with url: /v1/auth/token/lookup-self (Caused by SSLError(SSLError(\"bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)\",),))"} - -ANSIBLE_ROLES_PATH=../ \ - ansible-playbook playbooks/install_dependencies.yml -v "$@" - -ANSIBLE_ROLES_PATH=../ \ - ansible-playbook playbooks/test_lookup_hashi_vault.yml -v "$@" diff --git a/test/integration/targets/incidental_selinux/aliases b/test/integration/targets/incidental_selinux/aliases deleted file mode 100644 index 6bda43bcedf..00000000000 --- a/test/integration/targets/incidental_selinux/aliases +++ /dev/null @@ -1,3 +0,0 @@ -needs/root -shippable/posix/incidental -skip/aix diff --git a/test/integration/targets/incidental_selinux/tasks/main.yml b/test/integration/targets/incidental_selinux/tasks/main.yml deleted file mode 100644 index 41fdca52204..00000000000 --- a/test/integration/targets/incidental_selinux/tasks/main.yml +++ /dev/null @@ -1,36 +0,0 @@ -# (c) 2017, Sam Doran - -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -- debug: - msg: SELinux is disabled - when: ansible_selinux is defined and ansible_selinux == False - -- debug: - msg: SELinux is {{ ansible_selinux.status }} - when: ansible_selinux is defined and ansible_selinux != False - -- include: selinux.yml - when: - - ansible_selinux is defined - - ansible_selinux != False - - ansible_selinux.status == 'enabled' - -- include: selogin.yml - when: - - ansible_selinux is defined - - ansible_selinux != False - - ansible_selinux.status == 'enabled' diff --git a/test/integration/targets/incidental_selinux/tasks/selinux.yml b/test/integration/targets/incidental_selinux/tasks/selinux.yml deleted file mode 100644 index 7fcba899cfc..00000000000 --- a/test/integration/targets/incidental_selinux/tasks/selinux.yml +++ /dev/null @@ -1,364 +0,0 @@ -# (c) 2017, Sam Doran - -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - - -# First Test -# ############################################################################## -# Test changing the state, which requires a reboot - -- name: TEST 1 | Get current SELinux config file contents - set_fact: - selinux_config_original: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" - before_test_sestatus: "{{ ansible_selinux }}" - -- debug: - var: "{{ item }}" - verbosity: 1 - with_items: - - selinux_config_original - - before_test_sestatus - - ansible_selinux - -- name: TEST 1 | Setup SELinux configuration for tests - selinux: - state: enforcing - policy: targeted - -- name: TEST 1 | Disable SELinux - selinux: - state: disabled - policy: targeted - register: _disable_test1 - -- debug: - var: _disable_test1 - verbosity: 1 - -- name: TEST 1 | Re-gather facts - setup: - -- name: TEST 1 | Assert that status was changed, reboot_required is True, a warning was displayed, and SELinux is configured properly - assert: - that: - - _disable_test1 is changed - - _disable_test1.reboot_required - - (_disable_test1.warnings | length ) >= 1 - - ansible_selinux.config_mode == 'disabled' - - ansible_selinux.type == 'targeted' - -- debug: - var: ansible_selinux - verbosity: 1 - -- name: TEST 1 | Disable SELinux again - selinux: - state: disabled - policy: targeted - register: _disable_test2 - -- debug: - var: _disable_test2 - verbosity: 1 - -- name: TEST 1 | Assert that no change is reported, a warnking was dispalyed, and reboot_required is True - assert: - that: - - _disable_test2 is not changed - - (_disable_test1.warnings | length ) >= 1 - - _disable_test2.reboot_required - -- name: TEST 1 | Get modified config file - set_fact: - selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" - -- debug: - var: selinux_config_after - verbosity: 1 - -- name: TEST 1 | Ensure SELinux config file is properly formatted - assert: - that: - - selinux_config_original | length == selinux_config_after | length - - selinux_config_after[selinux_config_after.index('SELINUX=disabled')] is search("^SELINUX=\w+$") - - selinux_config_after[selinux_config_after.index('SELINUXTYPE=targeted')] is search("^SELINUXTYPE=\w+$") - -- name: TEST 1 | Reset SELinux configuration for next test - selinux: - state: enforcing - policy: targeted - - -# Second Test -# ############################################################################## -# Test changing only the policy, which does not require a reboot - -- name: TEST 2 | Make sure the policy is present - package: - name: selinux-policy-mls - state: present - -- name: TEST 2 | Set SELinux policy - selinux: - state: enforcing - policy: mls - register: _state_test1 - -- debug: - var: _state_test1 - verbosity: 1 - -- name: TEST 2 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - tags: debug - -- name: TEST 2 | Assert that status was changed, reboot_required is False, no warnings were displayed, and SELinux is configured properly - assert: - that: - - _state_test1 is changed - - not _state_test1.reboot_required - - _state_test1.warnings is not defined - - ansible_selinux.config_mode == 'enforcing' - - ansible_selinux.type == 'mls' - -- name: TEST 2 | Set SELinux policy again - selinux: - state: enforcing - policy: mls - register: _state_test2 - -- debug: - var: _state_test2 - verbosity: 1 - -- name: TEST 2 | Assert that no change was reported, no warnings were dispalyed, and reboot_required is False - assert: - that: - - _state_test2 is not changed - - _state_test2.warnings is not defined - - not _state_test2.reboot_required - -- name: TEST 2 | Get modified config file - set_fact: - selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" - -- debug: - var: selinux_config_after - verbosity: 1 - -- name: TEST 2 | Ensure SELinux config file is properly formatted - assert: - that: - - selinux_config_original | length == selinux_config_after | length - - selinux_config_after[selinux_config_after.index('SELINUX=enforcing')] is search("^SELINUX=\w+$") - - selinux_config_after[selinux_config_after.index('SELINUXTYPE=mls')] is search("^SELINUXTYPE=\w+$") - -- name: TEST 2 | Reset SELinux configuration for next test - selinux: - state: enforcing - policy: targeted - - -# Third Test -# ############################################################################## -# Test changing non-existing policy - -- name: TEST 3 | Set SELinux policy - selinux: - state: enforcing - policy: non-existing-selinux-policy - register: _state_test1 - ignore_errors: yes - -- debug: - var: _state_test1 - verbosity: 1 - -- name: TEST 3 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - tags: debug - -- name: TEST 3 | Assert that status was not changed, the task failed, the msg contains proper information and SELinux was not changed - assert: - that: - - _state_test1 is not changed - - _state_test1 is failed - - _state_test1.msg == 'Policy non-existing-selinux-policy does not exist in /etc/selinux/' - - ansible_selinux.config_mode == 'enforcing' - - ansible_selinux.type == 'targeted' - - -# Fourth Test -# ############################################################################## -# Test if check mode returns correct changed values and -# doesn't make any changes - - -- name: TEST 4 | Set SELinux to enforcing - selinux: - state: enforcing - policy: targeted - register: _check_mode_test1 - -- debug: - var: _check_mode_test1 - verbosity: 1 - -- name: TEST 4 | Set SELinux to enforcing in check mode - selinux: - state: enforcing - policy: targeted - register: _check_mode_test1 - check_mode: yes - -- name: TEST 4 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - verbosity: 1 - tags: debug - -- name: TEST 4 | Assert that check mode is idempotent - assert: - that: - - _check_mode_test1 is success - - not _check_mode_test1.reboot_required - - ansible_selinux.config_mode == 'enforcing' - - ansible_selinux.type == 'targeted' - -- name: TEST 4 | Set SELinux to permissive in check mode - selinux: - state: permissive - policy: targeted - register: _check_mode_test2 - check_mode: yes - -- name: TEST 4 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - verbosity: 1 - tags: debug - -- name: TEST 4 | Assert that check mode doesn't set state permissive and returns changed - assert: - that: - - _check_mode_test2 is changed - - not _check_mode_test2.reboot_required - - ansible_selinux.config_mode == 'enforcing' - - ansible_selinux.type == 'targeted' - -- name: TEST 4 | Disable SELinux in check mode - selinux: - state: disabled - register: _check_mode_test3 - check_mode: yes - -- name: TEST 4 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - verbosity: 1 - tags: debug - -- name: TEST 4 | Assert that check mode didn't change anything, status is changed, reboot_required is True, a warning was displayed - assert: - that: - - _check_mode_test3 is changed - - _check_mode_test3.reboot_required - - (_check_mode_test3.warnings | length ) >= 1 - - ansible_selinux.config_mode == 'enforcing' - - ansible_selinux.type == 'targeted' - -- name: TEST 4 | Set SELinux to permissive - selinux: - state: permissive - policy: targeted - register: _check_mode_test4 - -- debug: - var: _check_mode_test4 - verbosity: 1 - -- name: TEST 4 | Disable SELinux in check mode - selinux: - state: disabled - register: _check_mode_test4 - check_mode: yes - -- name: TEST 4 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - verbosity: 1 - tags: debug - -- name: TEST 4 | Assert that check mode didn't change anything, status is changed, reboot_required is True, a warning was displayed - assert: - that: - - _check_mode_test4 is changed - - _check_mode_test4.reboot_required - - (_check_mode_test3.warnings | length ) >= 1 - - ansible_selinux.config_mode == 'permissive' - - ansible_selinux.type == 'targeted' - -- name: TEST 4 | Set SELinux to enforcing - selinux: - state: enforcing - policy: targeted - register: _check_mode_test5 - -- debug: - var: _check_mode_test5 - verbosity: 1 - -- name: TEST 4 | Disable SELinux - selinux: - state: disabled - register: _check_mode_test5 - -- name: TEST 4 | Disable SELinux in check mode - selinux: - state: disabled - register: _check_mode_test5 - check_mode: yes - -- name: TEST 4 | Re-gather facts - setup: - -- debug: - var: ansible_selinux - verbosity: 1 - tags: debug - -- name: TEST 4 | Assert that in check mode status was not changed, reboot_required is True, a warning was displayed, and SELinux is configured properly - assert: - that: - - _check_mode_test5 is success - - _check_mode_test5.reboot_required - - (_check_mode_test5.warnings | length ) >= 1 - - ansible_selinux.config_mode == 'disabled' - - ansible_selinux.type == 'targeted' diff --git a/test/integration/targets/incidental_selinux/tasks/selogin.yml b/test/integration/targets/incidental_selinux/tasks/selogin.yml deleted file mode 100644 index a2c820ff38b..00000000000 --- a/test/integration/targets/incidental_selinux/tasks/selogin.yml +++ /dev/null @@ -1,81 +0,0 @@ ---- - -- name: create user for testing - user: - name: seuser - -- name: attempt to add mapping without 'seuser' - selogin: - login: seuser - register: selogin_error - ignore_errors: yes - -- name: verify failure - assert: - that: - - selogin_error is failed - -- name: map login to SELinux user - selogin: - login: seuser - seuser: staff_u - register: selogin_new_mapping - check_mode: "{{ item }}" - with_items: - - yes - - no - - yes - - no - -- name: new mapping- verify functionality and check_mode - assert: - that: - - selogin_new_mapping.results[0] is changed - - selogin_new_mapping.results[1] is changed - - selogin_new_mapping.results[2] is not changed - - selogin_new_mapping.results[3] is not changed - -- name: change SELinux user login mapping - selogin: - login: seuser - seuser: user_u - register: selogin_mod_mapping - check_mode: "{{ item }}" - with_items: - - yes - - no - - yes - - no - -- name: changed mapping- verify functionality and check_mode - assert: - that: - - selogin_mod_mapping.results[0] is changed - - selogin_mod_mapping.results[1] is changed - - selogin_mod_mapping.results[2] is not changed - - selogin_mod_mapping.results[3] is not changed - -- name: remove SELinux user mapping - selogin: - login: seuser - state: absent - register: selogin_del_mapping - check_mode: "{{ item }}" - with_items: - - yes - - no - - yes - - no - -- name: delete mapping- verify functionality and check_mode - assert: - that: - - selogin_del_mapping.results[0] is changed - - selogin_del_mapping.results[1] is changed - - selogin_del_mapping.results[2] is not changed - - selogin_del_mapping.results[3] is not changed - -- name: remove test user - user: - name: seuser - state: absent diff --git a/test/integration/targets/incidental_win_hosts/aliases b/test/integration/targets/incidental_win_hosts/aliases deleted file mode 100644 index a5fc90dcf48..00000000000 --- a/test/integration/targets/incidental_win_hosts/aliases +++ /dev/null @@ -1,2 +0,0 @@ -shippable/windows/incidental -windows diff --git a/test/integration/targets/incidental_win_hosts/defaults/main.yml b/test/integration/targets/incidental_win_hosts/defaults/main.yml deleted file mode 100644 index c6270216d68..00000000000 --- a/test/integration/targets/incidental_win_hosts/defaults/main.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -test_win_hosts_cname: testhost -test_win_hosts_ip: 192.168.168.1 - -test_win_hosts_aliases_set: - - alias1 - - alias2 - - alias3 - - alias4 - -test_win_hosts_aliases_remove: - - alias3 - - alias4 diff --git a/test/integration/targets/incidental_win_hosts/meta/main.yml b/test/integration/targets/incidental_win_hosts/meta/main.yml deleted file mode 100644 index 9f37e96cd90..00000000000 --- a/test/integration/targets/incidental_win_hosts/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: -- setup_remote_tmp_dir diff --git a/test/integration/targets/incidental_win_hosts/tasks/main.yml b/test/integration/targets/incidental_win_hosts/tasks/main.yml deleted file mode 100644 index 0997375f9fd..00000000000 --- a/test/integration/targets/incidental_win_hosts/tasks/main.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: take a copy of the original hosts file - win_copy: - src: C:\Windows\System32\drivers\etc\hosts - dest: '{{ remote_tmp_dir }}\hosts' - remote_src: yes - -- block: - - name: run tests - include_tasks: tests.yml - - always: - - name: restore hosts file - win_copy: - src: '{{ remote_tmp_dir }}\hosts' - dest: C:\Windows\System32\drivers\etc\hosts - remote_src: yes diff --git a/test/integration/targets/incidental_win_hosts/tasks/tests.yml b/test/integration/targets/incidental_win_hosts/tasks/tests.yml deleted file mode 100644 index a29e01a708b..00000000000 --- a/test/integration/targets/incidental_win_hosts/tasks/tests.yml +++ /dev/null @@ -1,189 +0,0 @@ ---- - -- name: add a simple host with address - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - register: add_ip - -- assert: - that: - - "add_ip.changed == true" - -- name: get actual dns result - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: add_ip_actual - -- assert: - that: - - "add_ip_actual.stdout_lines[0]|lower == 'true'" - -- name: add a simple host with ipv4 address (idempotent) - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - register: add_ip - -- assert: - that: - - "add_ip.changed == false" - -- name: remove simple host - win_hosts: - state: absent - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - register: remove_ip - -- assert: - that: - - "remove_ip.changed == true" - -- name: get actual dns result - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname}}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: remove_ip_actual - failed_when: "remove_ip_actual.rc == 0" - -- assert: - that: - - "remove_ip_actual.stdout_lines[0]|lower == 'false'" - -- name: remove simple host (idempotent) - win_hosts: - state: absent - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - register: remove_ip - -- assert: - that: - - "remove_ip.changed == false" - -- name: add host and set aliases - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}" - action: set - register: set_aliases - -- assert: - that: - - "set_aliases.changed == true" - -- name: get actual dns result for host - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ test_win_hosts_cname }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: set_aliases_actual_host - -- assert: - that: - - "set_aliases_actual_host.stdout_lines[0]|lower == 'true'" - -- name: get actual dns results for aliases - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: set_aliases_actual - with_items: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}" - -- assert: - that: - - "item.stdout_lines[0]|lower == 'true'" - with_items: "{{ set_aliases_actual.results }}" - -- name: add host and set aliases (idempotent) - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}" - action: set - register: set_aliases - -- assert: - that: - - "set_aliases.changed == false" - -- name: remove aliases from the list - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_remove }}" - action: remove - register: remove_aliases - -- assert: - that: - - "remove_aliases.changed == true" - -- name: get actual dns result for removed aliases - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: remove_aliases_removed_actual - failed_when: "remove_aliases_removed_actual.rc == 0" - with_items: "{{ test_win_hosts_aliases_remove }}" - -- assert: - that: - - "item.stdout_lines[0]|lower == 'false'" - with_items: "{{ remove_aliases_removed_actual.results }}" - -- name: get actual dns result for remaining aliases - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: remove_aliases_remain_actual - with_items: "{{ test_win_hosts_aliases_set | difference(test_win_hosts_aliases_remove) }}" - -- assert: - that: - - "item.stdout_lines[0]|lower == 'true'" - with_items: "{{ remove_aliases_remain_actual.results }}" - -- name: remove aliases from the list (idempotent) - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_remove }}" - action: remove - register: remove_aliases - -- assert: - that: - - "remove_aliases.changed == false" - -- name: add aliases back - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_remove }}" - action: add - register: add_aliases - -- assert: - that: - - "add_aliases.changed == true" - -- name: get actual dns results for aliases - win_shell: "try{ [array]$t = [Net.DNS]::GetHostEntry('{{ item }}') } catch { return 'false' } if ($t[0].HostName -eq '{{ test_win_hosts_cname }}' -and $t[0].AddressList[0].toString() -eq '{{ test_win_hosts_ip }}'){ return 'true' } else { return 'false' }" - register: add_aliases_actual - with_items: "{{ test_win_hosts_aliases_set | union(test_win_hosts_aliases_remove) }}" - -- assert: - that: - - "item.stdout_lines[0]|lower == 'true'" - with_items: "{{ add_aliases_actual.results }}" - -- name: add aliases back (idempotent) - win_hosts: - state: present - ip_address: "{{ test_win_hosts_ip }}" - canonical_name: "{{ test_win_hosts_cname }}" - aliases: "{{ test_win_hosts_aliases_remove }}" - action: add - register: add_aliases - -- assert: - that: - - "add_aliases.changed == false" diff --git a/test/support/integration/plugins/connection/chroot.py b/test/support/integration/plugins/connection/chroot.py deleted file mode 100644 index d95497b42b9..00000000000 --- a/test/support/integration/plugins/connection/chroot.py +++ /dev/null @@ -1,208 +0,0 @@ -# Based on local.py (c) 2012, Michael DeHaan -# -# (c) 2013, Maykel Moya -# (c) 2015, Toshio Kuratomi -# Copyright (c) 2017 Ansible Project -# 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 = """ - author: Maykel Moya - connection: chroot - short_description: Interact with local chroot - description: - - Run commands or put/fetch files to an existing chroot on the Ansible controller. - version_added: "1.1" - options: - remote_addr: - description: - - The path of the chroot you want to access. - default: inventory_hostname - vars: - - name: ansible_host - executable: - description: - - User specified executable shell - ini: - - section: defaults - key: executable - env: - - name: ANSIBLE_EXECUTABLE - vars: - - name: ansible_executable - default: /bin/sh - chroot_exe: - version_added: '2.8' - description: - - User specified chroot binary - ini: - - section: chroot_connection - key: exe - env: - - name: ANSIBLE_CHROOT_EXE - vars: - - name: ansible_chroot_exe - default: chroot -""" - -import os -import os.path -import subprocess -import traceback - -from ansible.errors import AnsibleError -from ansible.module_utils.basic import is_executable -from ansible.module_utils.common.process import get_bin_path -from ansible.module_utils.six.moves import shlex_quote -from ansible.module_utils._text import to_bytes, to_native -from ansible.plugins.connection import ConnectionBase, BUFSIZE -from ansible.utils.display import Display - -display = Display() - - -class Connection(ConnectionBase): - ''' Local chroot based connections ''' - - transport = 'chroot' - has_pipelining = True - # su currently has an undiagnosed issue with calculating the file - # checksums (so copy, for instance, doesn't work right) - # Have to look into that before re-enabling this - has_tty = False - - default_user = 'root' - - def __init__(self, play_context, new_stdin, *args, **kwargs): - super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs) - - self.chroot = self._play_context.remote_addr - - if os.geteuid() != 0: - raise AnsibleError("chroot connection requires running as root") - - # we're running as root on the local system so do some - # trivial checks for ensuring 'host' is actually a chroot'able dir - if not os.path.isdir(self.chroot): - raise AnsibleError("%s is not a directory" % self.chroot) - - chrootsh = os.path.join(self.chroot, 'bin/sh') - # Want to check for a usable bourne shell inside the chroot. - # is_executable() == True is sufficient. For symlinks it - # gets really complicated really fast. So we punt on finding that - # out. As long as it's a symlink we assume that it will work - if not (is_executable(chrootsh) or (os.path.lexists(chrootsh) and os.path.islink(chrootsh))): - raise AnsibleError("%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot) - - def _connect(self): - ''' connect to the chroot ''' - if os.path.isabs(self.get_option('chroot_exe')): - self.chroot_cmd = self.get_option('chroot_exe') - else: - try: - self.chroot_cmd = get_bin_path(self.get_option('chroot_exe')) - except ValueError as e: - raise AnsibleError(to_native(e)) - - super(Connection, self)._connect() - if not self._connected: - display.vvv("THIS IS A LOCAL CHROOT DIR", host=self.chroot) - self._connected = True - - def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE): - ''' run a command on the chroot. This is only needed for implementing - put_file() get_file() so that we don't have to read the whole file - into memory. - - compared to exec_command() it looses some niceties like being able to - return the process's exit code immediately. - ''' - executable = self.get_option('executable') - local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd] - - display.vvv("EXEC %s" % (local_cmd), host=self.chroot) - local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd] - p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - return p - - def exec_command(self, cmd, in_data=None, sudoable=False): - ''' run a command on the chroot ''' - super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) - - p = self._buffered_exec_command(cmd) - - stdout, stderr = p.communicate(in_data) - return (p.returncode, stdout, stderr) - - def _prefix_login_path(self, remote_path): - ''' Make sure that we put files into a standard path - - If a path is relative, then we need to choose where to put it. - ssh chooses $HOME but we aren't guaranteed that a home dir will - exist in any given chroot. So for now we're choosing "/" instead. - This also happens to be the former default. - - Can revisit using $HOME instead if it's a problem - ''' - if not remote_path.startswith(os.path.sep): - remote_path = os.path.join(os.path.sep, remote_path) - return os.path.normpath(remote_path) - - def put_file(self, in_path, out_path): - ''' transfer a file from local to chroot ''' - super(Connection, self).put_file(in_path, out_path) - display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot) - - out_path = shlex_quote(self._prefix_login_path(out_path)) - try: - with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file: - if not os.fstat(in_file.fileno()).st_size: - count = ' count=0' - else: - count = '' - try: - p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file) - except OSError: - raise AnsibleError("chroot connection requires dd command in the chroot") - try: - stdout, stderr = p.communicate() - except Exception: - traceback.print_exc() - raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path)) - if p.returncode != 0: - raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr)) - except IOError: - raise AnsibleError("file or module does not exist at: %s" % in_path) - - def fetch_file(self, in_path, out_path): - ''' fetch a file from chroot to local ''' - super(Connection, self).fetch_file(in_path, out_path) - display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot) - - in_path = shlex_quote(self._prefix_login_path(in_path)) - try: - p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) - except OSError: - raise AnsibleError("chroot connection requires dd command in the chroot") - - with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file: - try: - chunk = p.stdout.read(BUFSIZE) - while chunk: - out_file.write(chunk) - chunk = p.stdout.read(BUFSIZE) - except Exception: - traceback.print_exc() - raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path)) - stdout, stderr = p.communicate() - if p.returncode != 0: - raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr)) - - def close(self): - ''' terminate the connection; nothing to do here ''' - super(Connection, self).close() - self._connected = False diff --git a/test/support/integration/plugins/lookup/hashi_vault.py b/test/support/integration/plugins/lookup/hashi_vault.py deleted file mode 100644 index b90fe586ca3..00000000000 --- a/test/support/integration/plugins/lookup/hashi_vault.py +++ /dev/null @@ -1,302 +0,0 @@ -# (c) 2015, Jonathan Davila -# (c) 2017 Ansible Project -# 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 = """ - lookup: hashi_vault - author: Jonathan Davila - version_added: "2.0" - short_description: retrieve secrets from HashiCorp's vault - requirements: - - hvac (python library) - description: - - retrieve secrets from HashiCorp's vault - notes: - - Due to a current limitation in the HVAC library there won't necessarily be an error if a bad endpoint is specified. - - As of Ansible 2.10, only the latest secret is returned when specifying a KV v2 path. - options: - secret: - description: query you are making. - required: True - token: - description: vault token. - env: - - name: VAULT_TOKEN - url: - description: URL to vault service. - env: - - name: VAULT_ADDR - default: 'http://127.0.0.1:8200' - username: - description: Authentication user name. - password: - description: Authentication password. - role_id: - description: Role id for a vault AppRole auth. - env: - - name: VAULT_ROLE_ID - secret_id: - description: Secret id for a vault AppRole auth. - env: - - name: VAULT_SECRET_ID - auth_method: - description: - - Authentication method to be used. - - C(userpass) is added in version 2.8. - env: - - name: VAULT_AUTH_METHOD - choices: - - userpass - - ldap - - approle - mount_point: - description: vault mount point, only required if you have a custom mount point. - default: ldap - ca_cert: - description: path to certificate to use for authentication. - aliases: [ cacert ] - validate_certs: - description: controls verification and validation of SSL certificates, mostly you only want to turn off with self signed ones. - type: boolean - default: True - namespace: - version_added: "2.8" - description: namespace where secrets reside. requires HVAC 0.7.0+ and Vault 0.11+. -""" - -EXAMPLES = """ -- debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello:value token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200')}}" - -- name: Return all secrets from a path - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200')}}" - -- name: Vault that requires authentication via LDAP - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello:value auth_method=ldap mount_point=ldap username=myuser password=mypas url=http://myvault:8200')}}" - -- name: Vault that requires authentication via username and password - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello:value auth_method=userpass username=myuser password=mypas url=http://myvault:8200')}}" - -- name: Using an ssl vault - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hola:value token=c975b780-d1be-8016-866b-01d0f9b688a5 url=https://myvault:8200 validate_certs=False')}}" - -- name: using certificate auth - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hi:value token=xxxx-xxx-xxx url=https://myvault:8200 validate_certs=True cacert=/cacert/path/ca.pem')}}" - -- name: authenticate with a Vault app role - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello:value auth_method=approle role_id=myroleid secret_id=mysecretid url=http://myvault:8200')}}" - -- name: Return all secrets from a path in a namespace - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200 namespace=teama/admins')}}" - -# When using KV v2 the PATH should include "data" between the secret engine mount and path (e.g. "secret/data/:path") -# see: https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version -- name: Return latest KV v2 secret from path - debug: - msg: "{{ lookup('hashi_vault', 'secret=secret/data/hello token=my_vault_token url=http://myvault_url:8200') }}" - - -""" - -RETURN = """ -_raw: - description: - - secrets(s) requested -""" - -import os - -from ansible.errors import AnsibleError -from ansible.module_utils.parsing.convert_bool import boolean -from ansible.plugins.lookup import LookupBase - -HAS_HVAC = False -try: - import hvac - HAS_HVAC = True -except ImportError: - HAS_HVAC = False - - -ANSIBLE_HASHI_VAULT_ADDR = 'http://127.0.0.1:8200' - -if os.getenv('VAULT_ADDR') is not None: - ANSIBLE_HASHI_VAULT_ADDR = os.environ['VAULT_ADDR'] - - -class HashiVault: - def __init__(self, **kwargs): - - self.url = kwargs.get('url', ANSIBLE_HASHI_VAULT_ADDR) - self.namespace = kwargs.get('namespace', None) - self.avail_auth_method = ['approle', 'userpass', 'ldap'] - - # split secret arg, which has format 'secret/hello:value' into secret='secret/hello' and secret_field='value' - s = kwargs.get('secret') - if s is None: - raise AnsibleError("No secret specified for hashi_vault lookup") - - s_f = s.rsplit(':', 1) - self.secret = s_f[0] - if len(s_f) >= 2: - self.secret_field = s_f[1] - else: - self.secret_field = '' - - self.verify = self.boolean_or_cacert(kwargs.get('validate_certs', True), kwargs.get('cacert', '')) - - # If a particular backend is asked for (and its method exists) we call it, otherwise drop through to using - # token auth. This means if a particular auth backend is requested and a token is also given, then we - # ignore the token and attempt authentication against the specified backend. - # - # to enable a new auth backend, simply add a new 'def auth_' method below. - # - self.auth_method = kwargs.get('auth_method', os.environ.get('VAULT_AUTH_METHOD')) - self.verify = self.boolean_or_cacert(kwargs.get('validate_certs', True), kwargs.get('cacert', '')) - if self.auth_method and self.auth_method != 'token': - try: - if self.namespace is not None: - self.client = hvac.Client(url=self.url, verify=self.verify, namespace=self.namespace) - else: - self.client = hvac.Client(url=self.url, verify=self.verify) - # prefixing with auth_ to limit which methods can be accessed - getattr(self, 'auth_' + self.auth_method)(**kwargs) - except AttributeError: - raise AnsibleError("Authentication method '%s' not supported." - " Available options are %r" % (self.auth_method, self.avail_auth_method)) - else: - self.token = kwargs.get('token', os.environ.get('VAULT_TOKEN', None)) - if self.token is None and os.environ.get('HOME'): - token_filename = os.path.join( - os.environ.get('HOME'), - '.vault-token' - ) - if os.path.exists(token_filename): - with open(token_filename) as token_file: - self.token = token_file.read().strip() - - if self.token is None: - raise AnsibleError("No Vault Token specified") - - if self.namespace is not None: - self.client = hvac.Client(url=self.url, token=self.token, verify=self.verify, namespace=self.namespace) - else: - self.client = hvac.Client(url=self.url, token=self.token, verify=self.verify) - - if not self.client.is_authenticated(): - raise AnsibleError("Invalid Hashicorp Vault Token Specified for hashi_vault lookup") - - def get(self): - data = self.client.read(self.secret) - - # Check response for KV v2 fields and flatten nested secret data. - # - # https://vaultproject.io/api/secret/kv/kv-v2.html#sample-response-1 - try: - # sentinel field checks - check_dd = data['data']['data'] - check_md = data['data']['metadata'] - # unwrap nested data - data = data['data'] - except KeyError: - pass - - if data is None: - raise AnsibleError("The secret %s doesn't seem to exist for hashi_vault lookup" % self.secret) - - if self.secret_field == '': - return data['data'] - - if self.secret_field not in data['data']: - raise AnsibleError("The secret %s does not contain the field '%s'. for hashi_vault lookup" % (self.secret, self.secret_field)) - - return data['data'][self.secret_field] - - def check_params(self, **kwargs): - username = kwargs.get('username') - if username is None: - raise AnsibleError("Authentication method %s requires a username" % self.auth_method) - - password = kwargs.get('password') - if password is None: - raise AnsibleError("Authentication method %s requires a password" % self.auth_method) - - mount_point = kwargs.get('mount_point') - - return username, password, mount_point - - def auth_userpass(self, **kwargs): - username, password, mount_point = self.check_params(**kwargs) - if mount_point is None: - mount_point = 'userpass' - - self.client.auth_userpass(username, password, mount_point=mount_point) - - def auth_ldap(self, **kwargs): - username, password, mount_point = self.check_params(**kwargs) - if mount_point is None: - mount_point = 'ldap' - - self.client.auth.ldap.login(username, password, mount_point=mount_point) - - def boolean_or_cacert(self, validate_certs, cacert): - validate_certs = boolean(validate_certs, strict=False) - '''' return a bool or cacert ''' - if validate_certs is True: - if cacert != '': - return cacert - else: - return True - else: - return False - - def auth_approle(self, **kwargs): - role_id = kwargs.get('role_id', os.environ.get('VAULT_ROLE_ID', None)) - if role_id is None: - raise AnsibleError("Authentication method app role requires a role_id") - - secret_id = kwargs.get('secret_id', os.environ.get('VAULT_SECRET_ID', None)) - if secret_id is None: - raise AnsibleError("Authentication method app role requires a secret_id") - - self.client.auth_approle(role_id, secret_id) - - -class LookupModule(LookupBase): - def run(self, terms, variables=None, **kwargs): - if not HAS_HVAC: - raise AnsibleError("Please pip install hvac to use the hashi_vault lookup module.") - - vault_args = terms[0].split() - vault_dict = {} - ret = [] - - for param in vault_args: - try: - key, value = param.split('=') - except ValueError: - raise AnsibleError("hashi_vault lookup plugin needs key=value pairs, but received %s" % terms) - vault_dict[key] = value - - if 'ca_cert' in vault_dict.keys(): - vault_dict['cacert'] = vault_dict['ca_cert'] - vault_dict.pop('ca_cert', None) - - vault_conn = HashiVault(**vault_dict) - - for term in terms: - key = term.split()[0] - value = vault_conn.get() - ret.append(value) - - return ret diff --git a/test/support/integration/plugins/modules/selinux.py b/test/support/integration/plugins/modules/selinux.py deleted file mode 100644 index 775c87104b0..00000000000 --- a/test/support/integration/plugins/modules/selinux.py +++ /dev/null @@ -1,266 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2012, Derek Carter -# 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 - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['stableinterface'], - 'supported_by': 'core' -} - -DOCUMENTATION = r''' ---- -module: selinux -short_description: Change policy and state of SELinux -description: - - Configures the SELinux mode and policy. - - A reboot may be required after usage. - - Ansible will not issue this reboot but will let you know when it is required. -version_added: "0.7" -options: - policy: - description: - - The name of the SELinux policy to use (e.g. C(targeted)) will be required if state is not C(disabled). - state: - description: - - The SELinux mode. - required: true - choices: [ disabled, enforcing, permissive ] - configfile: - description: - - The path to the SELinux configuration file, if non-standard. - default: /etc/selinux/config - aliases: [ conf, file ] -requirements: [ libselinux-python ] -author: -- Derek Carter (@goozbach) -''' - -EXAMPLES = r''' -- name: Enable SELinux - selinux: - policy: targeted - state: enforcing - -- name: Put SELinux in permissive mode, logging actions that would be blocked. - selinux: - policy: targeted - state: permissive - -- name: Disable SELinux - selinux: - state: disabled -''' - -RETURN = r''' -msg: - description: Messages that describe changes that were made. - returned: always - type: str - sample: Config SELinux state changed from 'disabled' to 'permissive' -configfile: - description: Path to SELinux configuration file. - returned: always - type: str - sample: /etc/selinux/config -policy: - description: Name of the SELinux policy. - returned: always - type: str - sample: targeted -state: - description: SELinux mode. - returned: always - type: str - sample: enforcing -reboot_required: - description: Whether or not an reboot is required for the changes to take effect. - returned: always - type: bool - sample: true -''' - -import os -import re -import tempfile -import traceback - -SELINUX_IMP_ERR = None -try: - import selinux - HAS_SELINUX = True -except ImportError: - SELINUX_IMP_ERR = traceback.format_exc() - HAS_SELINUX = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib -from ansible.module_utils.facts.utils import get_file_lines - - -# getter subroutines -def get_config_state(configfile): - lines = get_file_lines(configfile, strip=False) - - for line in lines: - stateline = re.match(r'^SELINUX=.*$', line) - if stateline: - return line.split('=')[1].strip() - - -def get_config_policy(configfile): - lines = get_file_lines(configfile, strip=False) - - for line in lines: - stateline = re.match(r'^SELINUXTYPE=.*$', line) - if stateline: - return line.split('=')[1].strip() - - -# setter subroutines -def set_config_state(module, state, configfile): - # SELINUX=permissive - # edit config file with state value - stateline = 'SELINUX=%s' % state - lines = get_file_lines(configfile, strip=False) - - tmpfd, tmpfile = tempfile.mkstemp() - - with open(tmpfile, "w") as write_file: - for line in lines: - write_file.write(re.sub(r'^SELINUX=.*', stateline, line) + '\n') - - module.atomic_move(tmpfile, configfile) - - -def set_state(module, state): - if state == 'enforcing': - selinux.security_setenforce(1) - elif state == 'permissive': - selinux.security_setenforce(0) - elif state == 'disabled': - pass - else: - msg = 'trying to set invalid runtime state %s' % state - module.fail_json(msg=msg) - - -def set_config_policy(module, policy, configfile): - if not os.path.exists('/etc/selinux/%s/policy' % policy): - module.fail_json(msg='Policy %s does not exist in /etc/selinux/' % policy) - - # edit config file with state value - # SELINUXTYPE=targeted - policyline = 'SELINUXTYPE=%s' % policy - lines = get_file_lines(configfile, strip=False) - - tmpfd, tmpfile = tempfile.mkstemp() - - with open(tmpfile, "w") as write_file: - for line in lines: - write_file.write(re.sub(r'^SELINUXTYPE=.*', policyline, line) + '\n') - - module.atomic_move(tmpfile, configfile) - - -def main(): - module = AnsibleModule( - argument_spec=dict( - policy=dict(type='str'), - state=dict(type='str', required='True', choices=['enforcing', 'permissive', 'disabled']), - configfile=dict(type='str', default='/etc/selinux/config', aliases=['conf', 'file']), - ), - supports_check_mode=True, - ) - - if not HAS_SELINUX: - module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR) - - # global vars - changed = False - msgs = [] - configfile = module.params['configfile'] - policy = module.params['policy'] - state = module.params['state'] - runtime_enabled = selinux.is_selinux_enabled() - runtime_policy = selinux.selinux_getpolicytype()[1] - runtime_state = 'disabled' - reboot_required = False - - if runtime_enabled: - # enabled means 'enforcing' or 'permissive' - if selinux.security_getenforce(): - runtime_state = 'enforcing' - else: - runtime_state = 'permissive' - - if not os.path.isfile(configfile): - module.fail_json(msg="Unable to find file {0}".format(configfile), - details="Please install SELinux-policy package, " - "if this package is not installed previously.") - - config_policy = get_config_policy(configfile) - config_state = get_config_state(configfile) - - # check to see if policy is set if state is not 'disabled' - if state != 'disabled': - if not policy: - module.fail_json(msg="Policy is required if state is not 'disabled'") - else: - if not policy: - policy = config_policy - - # check changed values and run changes - if policy != runtime_policy: - if module.check_mode: - module.exit_json(changed=True) - # cannot change runtime policy - msgs.append("Running SELinux policy changed from '%s' to '%s'" % (runtime_policy, policy)) - changed = True - - if policy != config_policy: - if module.check_mode: - module.exit_json(changed=True) - set_config_policy(module, policy, configfile) - msgs.append("SELinux policy configuration in '%s' changed from '%s' to '%s'" % (configfile, config_policy, policy)) - changed = True - - if state != runtime_state: - if runtime_enabled: - if state == 'disabled': - if runtime_state != 'permissive': - # Temporarily set state to permissive - if not module.check_mode: - set_state(module, 'permissive') - module.warn("SELinux state temporarily changed from '%s' to 'permissive'. State change will take effect next reboot." % (runtime_state)) - changed = True - else: - module.warn('SELinux state change will take effect next reboot') - reboot_required = True - else: - if not module.check_mode: - set_state(module, state) - msgs.append("SELinux state changed from '%s' to '%s'" % (runtime_state, state)) - - # Only report changes if the file is changed. - # This prevents the task from reporting changes every time the task is run. - changed = True - else: - module.warn("Reboot is required to set SELinux state to '%s'" % state) - reboot_required = True - - if state != config_state: - if not module.check_mode: - set_config_state(module, state, configfile) - msgs.append("Config SELinux state changed from '%s' to '%s'" % (config_state, state)) - changed = True - - module.exit_json(changed=changed, msg=', '.join(msgs), configfile=configfile, policy=policy, state=state, reboot_required=reboot_required) - - -if __name__ == '__main__': - main() diff --git a/test/support/windows-integration/plugins/modules/win_hosts.ps1 b/test/support/windows-integration/plugins/modules/win_hosts.ps1 deleted file mode 100644 index 9e617c66643..00000000000 --- a/test/support/windows-integration/plugins/modules/win_hosts.ps1 +++ /dev/null @@ -1,257 +0,0 @@ -#!powershell - -# Copyright: (c) 2018, Micah Hunsberger (@mhunsber) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -#AnsibleRequires -CSharpUtil Ansible.Basic - -Set-StrictMode -Version 2 -$ErrorActionPreference = "Stop" - -$spec = @{ - options = @{ - state = @{ type = "str"; choices = "absent", "present"; default = "present" } - aliases = @{ type = "list"; elements = "str" } - canonical_name = @{ type = "str" } - ip_address = @{ type = "str" } - action = @{ type = "str"; choices = "add", "remove", "set"; default = "set" } - } - required_if = @(,@( "state", "present", @("canonical_name", "ip_address"))) - supports_check_mode = $true -} - -$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) - -$state = $module.Params.state -$aliases = $module.Params.aliases -$canonical_name = $module.Params.canonical_name -$ip_address = $module.Params.ip_address -$action = $module.Params.action - -$tmp = [ipaddress]::None -if($ip_address -and -not [ipaddress]::TryParse($ip_address, [ref]$tmp)){ - $module.FailJson("win_hosts: Argument ip_address needs to be a valid ip address, but was $ip_address") -} -$ip_address_type = $tmp.AddressFamily - -$hosts_file = Get-Item -LiteralPath "$env:SystemRoot\System32\drivers\etc\hosts" - -Function Get-CommentIndex($line) { - $c_index = $line.IndexOf('#') - if($c_index -lt 0) { - $c_index = $line.Length - } - return $c_index -} - -Function Get-HostEntryParts($line) { - $success = $true - $c_index = Get-CommentIndex -line $line - $pure_line = $line.Substring(0,$c_index).Trim() - $bits = $pure_line -split "\s+" - if($bits.Length -lt 2){ - return @{ - success = $false - ip_address = "" - ip_type = "" - canonical_name = "" - aliases = @() - } - } - $ip_obj = [ipaddress]::None - if(-not [ipaddress]::TryParse($bits[0], [ref]$ip_obj) ){ - $success = $false - } - $cname = $bits[1] - $als = New-Object string[] ($bits.Length - 2) - [array]::Copy($bits, 2, $als, 0, $als.Length) - return @{ - success = $success - ip_address = $ip_obj.IPAddressToString - ip_type = $ip_obj.AddressFamily - canonical_name = $cname - aliases = $als - } -} - -Function Find-HostName($line, $name) { - $c_idx = Get-CommentIndex -line $line - $re = New-Object regex ("\s+$($name.Replace('.',"\."))(\s|$)", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) - $match = $re.Match($line, 0, $c_idx) - return $match -} - -Function Remove-HostEntry($list, $idx) { - $module.Result.changed = $true - $list.RemoveAt($idx) -} - -Function Add-HostEntry($list, $cname, $aliases, $ip) { - $module.Result.changed = $true - $line = "$ip $cname $($aliases -join ' ')" - $list.Add($line) | Out-Null -} - -Function Remove-HostnamesFromEntry($list, $idx, $aliases) { - $line = $list[$idx] - $line_removed = $false - - foreach($name in $aliases){ - $match = Find-HostName -line $line -name $name - if($match.Success){ - $line = $line.Remove($match.Index + 1, $match.Length -1) - # was this the last alias? (check for space characters after trimming) - if($line.Substring(0,(Get-CommentIndex -line $line)).Trim() -inotmatch "\s") { - $list.RemoveAt($idx) - $line_removed = $true - # we're done - return @{ - line_removed = $line_removed - } - } - } - } - if($line -ne $list[$idx]){ - $module.Result.changed = $true - $list[$idx] = $line - } - return @{ - line_removed = $line_removed - } -} - -Function Add-AliasesToEntry($list, $idx, $aliases) { - $line = $list[$idx] - foreach($name in $aliases){ - $match = Find-HostName -line $line -name $name - if(-not $match.Success) { - # just add the alias before the comment - $line = $line.Insert((Get-CommentIndex -line $line), " $name ") - } - } - if($line -ne $list[$idx]){ - $module.Result.changed = $true - $list[$idx] = $line - } -} - -$hosts_lines = New-Object System.Collections.ArrayList - -Get-Content -LiteralPath $hosts_file.FullName | ForEach-Object { $hosts_lines.Add($_) } | Out-Null -$module.Diff.before = ($hosts_lines -join "`n") + "`n" - -if ($state -eq 'absent') { - # go through and remove canonical_name and ip - for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) { - $entry = $hosts_lines[$idx] - # skip comment lines - if(-not $entry.Trim().StartsWith('#')) { - $entry_parts = Get-HostEntryParts -line $entry - if($entry_parts.success) { - if(-not $ip_address -or $entry_parts.ip_address -eq $ip_address) { - if(-not $canonical_name -or $entry_parts.canonical_name -eq $canonical_name) { - if(Remove-HostEntry -list $hosts_lines -idx $idx){ - # keep index correct if we removed the line - $idx = $idx - 1 - } - } - } - } - } - } -} -if($state -eq 'present') { - $entry_idx = -1 - $aliases_to_keep = @() - # go through lines, find the entry and determine what to remove based on action - for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) { - $entry = $hosts_lines[$idx] - # skip comment lines - if(-not $entry.Trim().StartsWith('#')) { - $entry_parts = Get-HostEntryParts -line $entry - if($entry_parts.success) { - $aliases_to_remove = @() - if($entry_parts.ip_address -eq $ip_address) { - if($entry_parts.canonical_name -eq $canonical_name) { - $entry_idx = $idx - - if($action -eq 'set') { - $aliases_to_remove = $entry_parts.aliases | Where-Object { $aliases -notcontains $_ } - } elseif($action -eq 'remove') { - $aliases_to_remove = $aliases - } - } else { - # this is the right ip_address, but not the cname we were looking for. - # we need to make sure none of aliases or canonical_name exist for this entry - # since the given canonical_name should be an A/AAAA record, - # and aliases should be cname records for the canonical_name. - $aliases_to_remove = $aliases + $canonical_name - } - } else { - # this is not the ip_address we are looking for - if ($ip_address_type -eq $entry_parts.ip_type) { - if ($entry_parts.canonical_name -eq $canonical_name) { - Remove-HostEntry -list $hosts_lines -idx $idx - $idx = $idx - 1 - if ($action -ne "set") { - # keep old aliases intact - $aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ } - } - } elseif ($action -eq "remove") { - $aliases_to_remove = $canonical_name - } elseif ($aliases -contains $entry_parts.canonical_name) { - Remove-HostEntry -list $hosts_lines -idx $idx - $idx = $idx - 1 - if ($action -eq "add") { - # keep old aliases intact - $aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ } - } - } else { - $aliases_to_remove = $aliases + $canonical_name - } - } else { - # TODO: Better ipv6 support. There is odd behavior for when an alias can be used for both ipv6 and ipv4 - } - } - - if($aliases_to_remove) { - if((Remove-HostnamesFromEntry -list $hosts_lines -idx $idx -aliases $aliases_to_remove).line_removed) { - $idx = $idx - 1 - } - } - } - } - } - - if($entry_idx -ge 0) { - $aliases_to_add = @() - $entry_parts = Get-HostEntryParts -line $hosts_lines[$entry_idx] - if($action -eq 'remove') { - $aliases_to_add = $aliases_to_keep | Where-Object { $entry_parts.aliases -notcontains $_ } - } else { - $aliases_to_add = ($aliases + $aliases_to_keep) | Where-Object { $entry_parts.aliases -notcontains $_ } - } - - if($aliases_to_add) { - Add-AliasesToEntry -list $hosts_lines -idx $entry_idx -aliases $aliases_to_add - } - } else { - # add the entry at the end - if($action -eq 'remove') { - if($aliases_to_keep) { - Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases $aliases_to_keep - } else { - Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name - } - } else { - Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases ($aliases + $aliases_to_keep) - } - } -} - -$module.Diff.after = ($hosts_lines -join "`n") + "`n" -if( $module.Result.changed -and -not $module.CheckMode ) { - Set-Content -LiteralPath $hosts_file.FullName -Value $hosts_lines -} - -$module.ExitJson() diff --git a/test/support/windows-integration/plugins/modules/win_hosts.py b/test/support/windows-integration/plugins/modules/win_hosts.py deleted file mode 100644 index 9fd2d1d10d2..00000000000 --- a/test/support/windows-integration/plugins/modules/win_hosts.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Micah Hunsberger (@mhunsber) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# this is a windows documentation stub. actual code lives in the .ps1 -# file of the same name - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = r''' ---- -module: win_hosts -version_added: '2.8' -short_description: Manages hosts file entries on Windows. -description: - - Manages hosts file entries on Windows. - - Maps IPv4 or IPv6 addresses to canonical names. - - Adds, removes, or sets cname records for ip and hostname pairs. - - Modifies %windir%\\system32\\drivers\\etc\\hosts. -options: - state: - description: - - Whether the entry should be present or absent. - - If only I(canonical_name) is provided when C(state=absent), then - all hosts entries with the canonical name of I(canonical_name) - will be removed. - - If only I(ip_address) is provided when C(state=absent), then all - hosts entries with the ip address of I(ip_address) will be removed. - - If I(ip_address) and I(canonical_name) are both omitted when - C(state=absent), then all hosts entries will be removed. - choices: - - absent - - present - default: present - type: str - canonical_name: - description: - - A canonical name for the host entry. - - required for C(state=present). - type: str - ip_address: - description: - - The ip address for the host entry. - - Can be either IPv4 (A record) or IPv6 (AAAA record). - - Required for C(state=present). - type: str - aliases: - description: - - A list of additional names (cname records) for the host entry. - - Only applicable when C(state=present). - type: list - action: - choices: - - add - - remove - - set - description: - - Controls the behavior of I(aliases). - - Only applicable when C(state=present). - - If C(add), each alias in I(aliases) will be added to the host entry. - - If C(set), each alias in I(aliases) will be added to the host entry, - and other aliases will be removed from the entry. - default: set - type: str -author: - - Micah Hunsberger (@mhunsber) -notes: - - Each canonical name can only be mapped to one IPv4 and one IPv6 address. - If I(canonical_name) is provided with C(state=present) and is found - to be mapped to another IP address that is the same type as, but unique - from I(ip_address), then I(canonical_name) and all I(aliases) will - be removed from the entry and added to an entry with the provided IP address. - - Each alias can only be mapped to one canonical name. If I(aliases) is provided - with C(state=present) and an alias is found to be mapped to another canonical - name, then the alias will be removed from the entry and either added to or removed - from (depending on I(action)) an entry with the provided canonical name. -seealso: - - module: win_template - - module: win_file - - module: win_copy -''' - -EXAMPLES = r''' -- name: Add 127.0.0.1 as an A record for localhost - win_hosts: - state: present - canonical_name: localhost - ip_address: 127.0.0.1 - -- name: Add ::1 as an AAAA record for localhost - win_hosts: - state: present - canonical_name: localhost - ip_address: '::1' - -- name: Remove 'bar' and 'zed' from the list of aliases for foo (192.168.1.100) - win_hosts: - state: present - canoncial_name: foo - ip_address: 192.168.1.100 - action: remove - aliases: - - bar - - zed - -- name: Remove hosts entries with canonical name 'bar' - win_hosts: - state: absent - canonical_name: bar - -- name: Remove 10.2.0.1 from the list of hosts - win_hosts: - state: absent - ip_address: 10.2.0.1 - -- name: Ensure all name resolution is handled by DNS - win_hosts: - state: absent -''' - -RETURN = r''' -'''