Fourth batch of incidental integration tests. (#67873)
* Copy in incidental posix tests. * Update incidental test aliases. * Update target names. * Add support plugins. * Fix paths. * Update ignores. * Update integration-aliases sanity test. * Add incidental tests to CI.
This commit is contained in:
parent
04666c9fa1
commit
7c8b046b5f
318 changed files with 38534 additions and 0 deletions
shippable.yml
test/integration/targets
incidental_assemble
incidental_cloud_init_data_facts
incidental_connection_chroot
incidental_consul
incidental_deploy_helper
incidental_flatpak_remote
incidental_inventory_docker_swarm
incidental_lookup_hashi_vault
incidental_lookup_rabbitmq
incidental_lvg
incidental_mongodb_parameter
incidental_postgresql_user
incidental_selinux
incidental_setup_docker
incidental_setup_flatpak_remote
incidental_setup_mongodb
|
@ -158,6 +158,22 @@ matrix:
|
|||
- env: T=linux/ubuntu1604/5
|
||||
- env: T=linux/ubuntu1804/5
|
||||
|
||||
- env: T=i/aix/7.2
|
||||
- env: T=i/osx/10.11
|
||||
- env: T=i/rhel/7.6
|
||||
- env: T=i/rhel/8.1
|
||||
- env: T=i/freebsd/11.1
|
||||
- env: T=i/freebsd/12.1
|
||||
- env: T=i/linux/centos6
|
||||
- env: T=i/linux/centos7
|
||||
- env: T=i/linux/centos8
|
||||
- env: T=i/linux/fedora30
|
||||
- env: T=i/linux/fedora31
|
||||
- env: T=i/linux/opensuse15py2
|
||||
- env: T=i/linux/opensuse15
|
||||
- env: T=i/linux/ubuntu1604
|
||||
- env: T=i/linux/ubuntu1804
|
||||
|
||||
- env: T=aws/2.7/1
|
||||
- env: T=aws/3.6/1
|
||||
|
||||
|
|
1
test/integration/targets/incidental_assemble/aliases
Normal file
1
test/integration/targets/incidental_assemble/aliases
Normal file
|
@ -0,0 +1 @@
|
|||
shippable/posix/incidental
|
|
@ -0,0 +1 @@
|
|||
this is fragment 1
|
|
@ -0,0 +1 @@
|
|||
this is fragment 2
|
|
@ -0,0 +1 @@
|
|||
this is fragment 3
|
|
@ -0,0 +1 @@
|
|||
this is fragment 4
|
|
@ -0,0 +1 @@
|
|||
this is fragment 5
|
101
test/integration/targets/incidental_assemble/tasks/main.yml
Normal file
101
test/integration/targets/incidental_assemble/tasks/main.yml
Normal file
|
@ -0,0 +1,101 @@
|
|||
# test code for the assemble module
|
||||
# (c) 2014, James Cammarata <jcammarata@ansible.com>
|
||||
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
- name: create a new directory for file source
|
||||
file: dest="{{output_dir}}/src" state=directory
|
||||
register: result
|
||||
|
||||
- name: assert the directory was created
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'directory'"
|
||||
|
||||
- name: copy the files to a new directory
|
||||
copy: src="./" dest="{{output_dir}}/src"
|
||||
register: result
|
||||
|
||||
- name: create unicode file for test
|
||||
shell: echo "π" > {{ output_dir }}/src/ßΩ.txt
|
||||
register: result
|
||||
|
||||
- name: assert that the new file was created
|
||||
assert:
|
||||
that:
|
||||
- "result.changed == true"
|
||||
|
||||
- name: test assemble with all fragments
|
||||
assemble: src="{{output_dir}}/src" dest="{{output_dir}}/assembled1"
|
||||
register: result
|
||||
|
||||
- name: assert the fragments were assembled
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.changed == True"
|
||||
- "result.checksum == '74152e9224f774191bc0bedf460d35de86ad90e6'"
|
||||
|
||||
- name: test assemble with all fragments
|
||||
assemble: src="{{output_dir}}/src" dest="{{output_dir}}/assembled1"
|
||||
register: result
|
||||
|
||||
- name: assert that the same assemble made no changes
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.changed == False"
|
||||
- "result.checksum == '74152e9224f774191bc0bedf460d35de86ad90e6'"
|
||||
|
||||
- name: test assemble with fragments matching a regex
|
||||
assemble: src="{{output_dir}}/src" dest="{{output_dir}}/assembled2" regexp="^fragment[1-3]$"
|
||||
register: result
|
||||
|
||||
- name: assert the fragments were assembled with a regex
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.checksum == 'edfe2d7487ef8f5ebc0f1c4dc57ba7b70a7b8e2b'"
|
||||
|
||||
- name: test assemble with a delimiter
|
||||
assemble: src="{{output_dir}}/src" dest="{{output_dir}}/assembled3" delimiter="#--- delimiter ---#"
|
||||
register: result
|
||||
|
||||
- name: assert the fragments were assembled with a delimiter
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.checksum == 'd986cefb82e34e4cf14d33a3cda132ff45aa2980'"
|
||||
|
||||
- name: test assemble with remote_src=False
|
||||
assemble: src="./" dest="{{output_dir}}/assembled4" remote_src=no
|
||||
register: result
|
||||
|
||||
- name: assert the fragments were assembled without remote
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.checksum == '048a1bd1951aa5ccc427eeb4ca19aee45e9c68b3'"
|
||||
|
||||
- name: test assemble with remote_src=False and a delimiter
|
||||
assemble: src="./" dest="{{output_dir}}/assembled5" remote_src=no delimiter="#--- delimiter ---#"
|
||||
register: result
|
||||
|
||||
- name: assert the fragments were assembled without remote
|
||||
assert:
|
||||
that:
|
||||
- "result.state == 'file'"
|
||||
- "result.checksum == '505359f48c65b3904127cf62b912991d4da7ed6d'"
|
|
@ -0,0 +1,5 @@
|
|||
destructive
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
- name: test cloud-init
|
||||
# TODO: check for a workaround
|
||||
# install 'cloud-init'' failed: dpkg-divert: error: `diversion of /etc/init/ureadahead.conf
|
||||
# to /etc/init/ureadahead.conf.disabled by cloud-init' clashes with `local diversion of
|
||||
# /etc/init/ureadahead.conf to /etc/init/ureadahead.conf.distrib
|
||||
# https://bugs.launchpad.net/ubuntu/+source/ureadahead/+bug/997838
|
||||
# Will also have to skip on OpenSUSE when running on Python 2 on newer Leap versions
|
||||
# (!= 42 and >= 15) ascloud-init will install the Python 3 package, breaking our build on py2.
|
||||
when:
|
||||
- not (ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int == 14)
|
||||
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and ansible_python.version.major != 3)
|
||||
block:
|
||||
- name: setup install cloud-init
|
||||
package:
|
||||
name:
|
||||
- cloud-init
|
||||
- udev
|
||||
|
||||
- name: setup run cloud-init
|
||||
service:
|
||||
name: cloud-init-local
|
||||
state: restarted
|
||||
|
||||
- name: test gather cloud-init facts in check mode
|
||||
cloud_init_data_facts:
|
||||
check_mode: yes
|
||||
register: result
|
||||
- name: verify test gather cloud-init facts in check mode
|
||||
assert:
|
||||
that:
|
||||
- result.cloud_init_data_facts.status.v1 is defined
|
||||
- result.cloud_init_data_facts.status.v1.stage is defined
|
||||
- not result.cloud_init_data_facts.status.v1.stage
|
||||
- cloud_init_data_facts.status.v1 is defined
|
||||
- cloud_init_data_facts.status.v1.stage is defined
|
||||
- not cloud_init_data_facts.status.v1.stage
|
||||
|
||||
- name: test gather cloud-init facts
|
||||
cloud_init_data_facts:
|
||||
register: result
|
||||
- name: verify test gather cloud-init facts
|
||||
assert:
|
||||
that:
|
||||
- result.cloud_init_data_facts.status.v1 is defined
|
||||
- result.cloud_init_data_facts.status.v1.stage is defined
|
||||
- not result.cloud_init_data_facts.status.v1.stage
|
||||
- cloud_init_data_facts.status.v1 is defined
|
||||
- cloud_init_data_facts.status.v1.stage is defined
|
||||
- not cloud_init_data_facts.status.v1.stage
|
|
@ -0,0 +1,3 @@
|
|||
needs/root
|
||||
shippable/posix/incidental
|
||||
needs/target/connection
|
18
test/integration/targets/incidental_connection_chroot/runme.sh
Executable file
18
test/integration/targets/incidental_connection_chroot/runme.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/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 \
|
||||
"$@"
|
|
@ -0,0 +1,7 @@
|
|||
[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 }}"
|
3
test/integration/targets/incidental_consul/aliases
Normal file
3
test/integration/targets/incidental_consul/aliases
Normal file
|
@ -0,0 +1,3 @@
|
|||
shippable/posix/incidental
|
||||
destructive
|
||||
skip/aix
|
3
test/integration/targets/incidental_consul/meta/main.yml
Normal file
3
test/integration/targets/incidental_consul/meta/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
dependencies:
|
||||
- incidental_setup_openssl
|
|
@ -0,0 +1,162 @@
|
|||
- name: list sessions
|
||||
consul_session:
|
||||
state: list
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- "'sessions' in result"
|
||||
|
||||
- name: create a session
|
||||
consul_session:
|
||||
state: present
|
||||
name: testsession
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result['name'] == 'testsession'
|
||||
- "'session_id' in result"
|
||||
|
||||
- set_fact:
|
||||
session_id: "{{ result['session_id'] }}"
|
||||
|
||||
- name: list sessions after creation
|
||||
consul_session:
|
||||
state: list
|
||||
register: result
|
||||
|
||||
- set_fact:
|
||||
session_count: "{{ result['sessions'] | length }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
# selectattr not available on Jinja 2.2 provided by CentOS 6
|
||||
# hence the two following tasks (set_fact/assert) are used
|
||||
# - (result['sessions'] | selectattr('ID', 'match', '^' ~ session_id ~ '$') | first)['Name'] == 'testsession'
|
||||
|
||||
- name: search created session
|
||||
set_fact:
|
||||
test_session_found: True
|
||||
loop: "{{ result['sessions'] }}"
|
||||
when: "item.get('ID') == session_id and item.get('Name') == 'testsession'"
|
||||
|
||||
- name: ensure session was created
|
||||
assert:
|
||||
that:
|
||||
- test_session_found|default(False)
|
||||
|
||||
- name: fetch info about a session
|
||||
consul_session:
|
||||
state: info
|
||||
id: '{{ session_id }}'
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: ensure 'id' parameter is required when state=info
|
||||
consul_session:
|
||||
state: info
|
||||
name: test
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is failed
|
||||
|
||||
- name: ensure unknown scheme fails
|
||||
consul_session:
|
||||
state: info
|
||||
id: '{{ session_id }}'
|
||||
scheme: non_existent
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is failed
|
||||
|
||||
- when: pyopenssl_version.stdout is version('0.15', '>=')
|
||||
block:
|
||||
- name: ensure SSL certificate is checked
|
||||
consul_session:
|
||||
state: info
|
||||
id: '{{ session_id }}'
|
||||
port: 8501
|
||||
scheme: https
|
||||
register: result
|
||||
ignore_errors: True
|
||||
|
||||
- name: previous task should fail since certificate is not known
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- "'certificate verify failed' in result.msg"
|
||||
|
||||
- name: ensure SSL certificate isn't checked when validate_certs is disabled
|
||||
consul_session:
|
||||
state: info
|
||||
id: '{{ session_id }}'
|
||||
port: 8501
|
||||
scheme: https
|
||||
validate_certs: False
|
||||
register: result
|
||||
|
||||
- name: previous task should succeed since certificate isn't checked
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: ensure a secure connection is possible
|
||||
consul_session:
|
||||
state: info
|
||||
id: '{{ session_id }}'
|
||||
port: 8501
|
||||
scheme: https
|
||||
environment:
|
||||
REQUESTS_CA_BUNDLE: '{{ remote_dir }}/cert.pem'
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: delete a session
|
||||
consul_session:
|
||||
state: absent
|
||||
id: '{{ session_id }}'
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: list sessions after deletion
|
||||
consul_session:
|
||||
state: list
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
# selectattr and equalto not available on Jinja 2.2 provided by CentOS 6
|
||||
# hence the two following tasks (command/assert) are used
|
||||
# - (result['sessions'] | selectattr('ID', 'equalto', session_id) | list | length) == 0
|
||||
|
||||
- name: search deleted session
|
||||
command: echo 'session found'
|
||||
loop: "{{ result['sessions'] }}"
|
||||
when: "item.get('ID') == session_id and item.get('Name') == 'testsession'"
|
||||
register: search_deleted
|
||||
|
||||
- name: ensure session was deleted
|
||||
assert:
|
||||
that:
|
||||
- search_deleted is skipped # each iteration is skipped
|
||||
- search_deleted is not changed # and then unchanged
|
97
test/integration/targets/incidental_consul/tasks/main.yml
Normal file
97
test/integration/targets/incidental_consul/tasks/main.yml
Normal file
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
- name: Install Consul and test
|
||||
|
||||
vars:
|
||||
consul_version: '1.5.0'
|
||||
consul_uri: https://s3.amazonaws.com/ansible-ci-files/test/integration/targets/consul/consul_{{ consul_version }}_{{ ansible_system | lower }}_{{ consul_arch }}.zip
|
||||
consul_cmd: '{{ output_dir }}/consul'
|
||||
|
||||
block:
|
||||
- name: register pyOpenSSL version
|
||||
command: "{{ ansible_python_interpreter }} -c 'import OpenSSL; print(OpenSSL.__version__)'"
|
||||
register: pyopenssl_version
|
||||
|
||||
- name: Install requests<2.20 (CentOS/RHEL 6)
|
||||
pip:
|
||||
name: requests<2.20
|
||||
register: result
|
||||
until: result is success
|
||||
when: ansible_distribution_file_variety|default() == 'RedHat' and ansible_distribution_major_version is version('6', '<=')
|
||||
|
||||
- name: Install python-consul
|
||||
pip:
|
||||
name: python-consul
|
||||
register: result
|
||||
until: result is success
|
||||
|
||||
- when: pyopenssl_version.stdout is version('0.15', '>=')
|
||||
block:
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
|
||||
- name: Generate CSR
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: localhost
|
||||
|
||||
- name: Generate selfsigned certificate
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/cert.pem'
|
||||
csr_path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
register: selfsigned_certificate
|
||||
|
||||
- name: 'Install unzip'
|
||||
package:
|
||||
name: unzip
|
||||
register: result
|
||||
until: result is success
|
||||
when: ansible_distribution != "MacOSX" # unzip already installed
|
||||
|
||||
- assert:
|
||||
# Linux: x86_64, FreeBSD: amd64
|
||||
that: ansible_architecture in ['i386', 'x86_64', 'amd64']
|
||||
- set_fact:
|
||||
consul_arch: '386'
|
||||
when: ansible_architecture == 'i386'
|
||||
- set_fact:
|
||||
consul_arch: amd64
|
||||
when: ansible_architecture in ['x86_64', 'amd64']
|
||||
|
||||
- name: 'Download consul binary'
|
||||
unarchive:
|
||||
src: '{{ consul_uri }}'
|
||||
dest: '{{ output_dir }}'
|
||||
remote_src: true
|
||||
register: result
|
||||
until: result is success
|
||||
|
||||
- vars:
|
||||
remote_dir: '{{ echo_output_dir.stdout }}'
|
||||
block:
|
||||
- command: 'echo {{ output_dir }}'
|
||||
register: echo_output_dir
|
||||
|
||||
- name: 'Create configuration file'
|
||||
template:
|
||||
src: consul_config.hcl.j2
|
||||
dest: '{{ output_dir }}/consul_config.hcl'
|
||||
|
||||
- name: 'Start Consul (dev mode enabled)'
|
||||
shell: 'nohup {{ consul_cmd }} agent -dev -config-file {{ output_dir }}/consul_config.hcl </dev/null >/dev/null 2>&1 &'
|
||||
|
||||
- name: 'Create some data'
|
||||
command: '{{ consul_cmd }} kv put data/value{{ item }} foo{{ item }}'
|
||||
loop: [1, 2, 3]
|
||||
|
||||
- import_tasks: consul_session.yml
|
||||
|
||||
always:
|
||||
- name: 'Kill consul process'
|
||||
shell: "kill $(cat {{ output_dir }}/consul.pid)"
|
||||
ignore_errors: true
|
|
@ -0,0 +1,13 @@
|
|||
# {{ ansible_managed }}
|
||||
server = true
|
||||
pid_file = "{{ remote_dir }}/consul.pid"
|
||||
ports {
|
||||
http = 8500
|
||||
{% if pyopenssl_version.stdout is version('0.15', '>=') %}
|
||||
https = 8501
|
||||
{% endif %}
|
||||
}
|
||||
{% if pyopenssl_version.stdout is version('0.15', '>=') %}
|
||||
key_file = "{{ remote_dir }}/privatekey.pem"
|
||||
cert_file = "{{ remote_dir }}/cert.pem"
|
||||
{% endif %}
|
|
@ -0,0 +1 @@
|
|||
shippable/posix/incidental
|
149
test/integration/targets/incidental_deploy_helper/tasks/main.yml
Normal file
149
test/integration/targets/incidental_deploy_helper/tasks/main.yml
Normal file
|
@ -0,0 +1,149 @@
|
|||
---
|
||||
- name: record the output directory
|
||||
set_fact: deploy_helper_test_root={{output_dir}}/deploy_helper_test_root
|
||||
|
||||
- name: State=query with default parameters
|
||||
deploy_helper: path={{ deploy_helper_test_root }} state=query
|
||||
- name: Assert State=query with default parameters
|
||||
assert:
|
||||
that:
|
||||
- "'project_path' in deploy_helper"
|
||||
- "deploy_helper.current_path == '{{ deploy_helper.project_path }}/current'"
|
||||
- "deploy_helper.releases_path == '{{ deploy_helper.project_path }}/releases'"
|
||||
- "deploy_helper.shared_path == '{{ deploy_helper.project_path }}/shared'"
|
||||
- "deploy_helper.unfinished_filename == 'DEPLOY_UNFINISHED'"
|
||||
- "'previous_release' in deploy_helper"
|
||||
- "'previous_release_path' in deploy_helper"
|
||||
- "'new_release' in deploy_helper"
|
||||
- "'new_release_path' in deploy_helper"
|
||||
- "deploy_helper.new_release_path == '{{ deploy_helper.releases_path }}/{{ deploy_helper.new_release }}'"
|
||||
|
||||
- name: State=query with relative overridden paths
|
||||
deploy_helper: path={{ deploy_helper_test_root }} current_path=CURRENT_PATH releases_path=RELEASES_PATH shared_path=SHARED_PATH state=query
|
||||
- name: Assert State=query with relative overridden paths
|
||||
assert:
|
||||
that:
|
||||
- "deploy_helper.current_path == '{{ deploy_helper.project_path }}/CURRENT_PATH'"
|
||||
- "deploy_helper.releases_path == '{{ deploy_helper.project_path }}/RELEASES_PATH'"
|
||||
- "deploy_helper.shared_path == '{{ deploy_helper.project_path }}/SHARED_PATH'"
|
||||
- "deploy_helper.new_release_path == '{{ deploy_helper.releases_path }}/{{ deploy_helper.new_release}}'"
|
||||
|
||||
- name: State=query with absolute overridden paths
|
||||
deploy_helper: path={{ deploy_helper_test_root }} current_path=/CURRENT_PATH releases_path=/RELEASES_PATH shared_path=/SHARED_PATH state=query
|
||||
- name: Assert State=query with absolute overridden paths
|
||||
assert:
|
||||
that:
|
||||
- "deploy_helper.current_path == '/CURRENT_PATH'"
|
||||
- "deploy_helper.releases_path == '/RELEASES_PATH'"
|
||||
- "deploy_helper.shared_path == '/SHARED_PATH'"
|
||||
- "deploy_helper.new_release_path == '{{ deploy_helper.releases_path }}/{{ deploy_helper.new_release}}'"
|
||||
|
||||
- name: State=query with overridden unfinished_filename
|
||||
deploy_helper: path={{ deploy_helper_test_root }} unfinished_filename=UNFINISHED_DEPLOY state=query
|
||||
- name: Assert State=query with overridden unfinished_filename
|
||||
assert:
|
||||
that:
|
||||
- "'UNFINISHED_DEPLOY' == deploy_helper.unfinished_filename"
|
||||
|
||||
# Remove the root folder just in case it exists
|
||||
- file: path={{ deploy_helper_test_root }} state=absent
|
||||
|
||||
- name: State=present with default parameters
|
||||
deploy_helper: path={{ deploy_helper_test_root }} state=present
|
||||
- stat: path={{ deploy_helper.releases_path }}
|
||||
register: releases_path
|
||||
- stat: path={{ deploy_helper.shared_path }}
|
||||
register: shared_path
|
||||
- name: Assert State=present with default parameters
|
||||
assert:
|
||||
that:
|
||||
- "releases_path.stat.exists"
|
||||
- "shared_path.stat.exists"
|
||||
|
||||
# Setup older releases for tests
|
||||
- file: path={{ deploy_helper.releases_path }}/{{ item }} state=directory
|
||||
with_items: ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh']
|
||||
# Setup the new release
|
||||
- file: path={{ deploy_helper.new_release_path }} state=directory
|
||||
# Add a buildfile, just like in a real deploy
|
||||
- copy: content='' dest={{ deploy_helper.new_release_path }}/{{ deploy_helper.unfinished_filename }}
|
||||
# Add a buildfile, to an older deploy
|
||||
- copy: content='' dest={{ deploy_helper.releases_path }}/third/{{ deploy_helper.unfinished_filename }}
|
||||
|
||||
- name: State=finalize with default parameters
|
||||
deploy_helper: path={{ deploy_helper_test_root }} release={{ deploy_helper.new_release }} state=finalize
|
||||
- stat: path={{ deploy_helper.current_path }}
|
||||
register: current_path
|
||||
- stat: path={{ deploy_helper.current_path }}/DEPLOY_UNFINISHED
|
||||
register: current_path_unfinished_filename
|
||||
- name: Assert State=finalize with default parameters
|
||||
assert:
|
||||
that:
|
||||
- "current_path.stat.islnk"
|
||||
- "deploy_helper.new_release_path in current_path.stat.lnk_source"
|
||||
- "not current_path_unfinished_filename.stat.exists"
|
||||
- stat: path={{ deploy_helper.releases_path }}/third
|
||||
register: third_release_path
|
||||
- shell: "ls {{ deploy_helper.releases_path }} | wc -l"
|
||||
register: releases_count
|
||||
- name: Assert State=finalize with default parameters (clean=true checks)
|
||||
assert:
|
||||
that:
|
||||
- "not third_release_path.stat.exists"
|
||||
- "releases_count.stdout|trim == '6'"
|
||||
- deploy_helper: path={{ deploy_helper_test_root }} release={{ deploy_helper.new_release }} state=query
|
||||
- name: Assert State=finalize with default parameters (previous_release checks)
|
||||
assert:
|
||||
that:
|
||||
- "deploy_helper.new_release == deploy_helper.previous_release"
|
||||
|
||||
- name: State=absent with default parameters
|
||||
deploy_helper: path={{ deploy_helper_test_root }} state=absent
|
||||
- stat: path={{ deploy_helper_test_root }}
|
||||
register: project_path
|
||||
- name: Assert State=absent with default parameters
|
||||
assert:
|
||||
that:
|
||||
- "not project_path.stat.exists"
|
||||
|
||||
- debug: msg="Clearing all release data and facts ---------"
|
||||
|
||||
- name: State=present with shared_path set to False
|
||||
deploy_helper: path={{ deploy_helper_test_root }} state=present shared_path=''
|
||||
- stat: path={{ deploy_helper.releases_path }}
|
||||
register: releases_path
|
||||
- stat: path={{ deploy_helper.shared_path }}
|
||||
register: shared_path
|
||||
- name: Assert State=present with shared_path set to False
|
||||
assert:
|
||||
that:
|
||||
- "releases_path.stat.exists"
|
||||
- "not shared_path.stat.exists"
|
||||
|
||||
# Setup older releases for tests
|
||||
- file: path={{ deploy_helper.releases_path }}/{{ item }} state=directory
|
||||
with_items: ['first', 'second', 'third', 'fourth', 'fifth']
|
||||
# Setup the new release
|
||||
- file: path={{ deploy_helper.new_release_path }} state=directory
|
||||
# Add a buildfile, just like in a real deploy
|
||||
- copy: content='' dest={{ deploy_helper.new_release_path }}/{{ deploy_helper.unfinished_filename }}
|
||||
# Add a buildfile, to an older deploy
|
||||
- copy: content='' dest={{ deploy_helper.releases_path }}/third/{{ deploy_helper.unfinished_filename }}
|
||||
|
||||
- shell: "ls {{ deploy_helper_test_root }}/releases | wc -l"
|
||||
register: before_releases_count
|
||||
- name: State=clean with keep_releases=3
|
||||
deploy_helper: path={{ deploy_helper_test_root }} release={{ deploy_helper.new_release }} state=clean keep_releases=3
|
||||
- stat: path={{ deploy_helper.releases_path }}/third
|
||||
register: third_release_path
|
||||
- shell: "ls {{ deploy_helper.releases_path }} | wc -l"
|
||||
register: releases_count
|
||||
- name: Assert State=finalize with default parameters (clean=true checks)
|
||||
assert:
|
||||
that:
|
||||
- "not third_release_path.stat.exists"
|
||||
- "before_releases_count.stdout|trim == '6'"
|
||||
- "releases_count.stdout|trim == '3'"
|
||||
|
||||
# Remove the root folder
|
||||
- file: path={{ deploy_helper_test_root }} state=absent
|
|
@ -0,0 +1,7 @@
|
|||
shippable/posix/incidental
|
||||
destructive
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/osx
|
||||
skip/rhel
|
||||
needs/root
|
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- incidental_setup_flatpak_remote
|
|
@ -0,0 +1,101 @@
|
|||
# - Tests with absent flatpak remote -------------------------------------------
|
||||
|
||||
# state=present
|
||||
|
||||
- name: Test addition of absent flatpak remote (check mode)
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
||||
register: addition_result
|
||||
check_mode: true
|
||||
|
||||
- name: Verify addition of absent flatpak remote test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "addition_result.changed == true"
|
||||
msg: "Adding an absent flatpak remote shall mark module execution as changed"
|
||||
|
||||
- name: Test non-existent idempotency of addition of absent flatpak remote (check mode)
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
||||
register: double_addition_result
|
||||
check_mode: true
|
||||
|
||||
- name: >
|
||||
Verify non-existent idempotency of addition of absent flatpak remote
|
||||
test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "double_addition_result.changed == true"
|
||||
msg: |
|
||||
Adding an absent flatpak remote a second time shall still mark module execution
|
||||
as changed in check mode
|
||||
|
||||
# state=absent
|
||||
|
||||
- name: Test removal of absent flatpak remote not doing anything in check mode
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
state: absent
|
||||
register: removal_result
|
||||
check_mode: true
|
||||
|
||||
- name: Verify removal of absent flatpak remote test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "removal_result.changed == false"
|
||||
msg: "Removing an absent flatpak remote shall mark module execution as not changed"
|
||||
|
||||
|
||||
# - Tests with present flatpak remote -------------------------------------------
|
||||
|
||||
# state=present
|
||||
|
||||
- name: Test addition of present flatpak remote (check mode)
|
||||
flatpak_remote:
|
||||
name: check-mode-test-remote
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
||||
register: addition_result
|
||||
check_mode: true
|
||||
|
||||
- name: Verify addition of present flatpak remote test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "addition_result.changed == false"
|
||||
msg: "Adding a present flatpak remote shall mark module execution as not changed"
|
||||
|
||||
# state=absent
|
||||
|
||||
- name: Test removal of present flatpak remote not doing anything in check mode
|
||||
flatpak_remote:
|
||||
name: check-mode-test-remote
|
||||
state: absent
|
||||
register: removal_result
|
||||
check_mode: true
|
||||
|
||||
- name: Verify removal of present flatpak remote test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "removal_result.changed == true"
|
||||
msg: "Removing a present flatpak remote shall mark module execution as changed"
|
||||
|
||||
- name: Test non-existent idempotency of removal of present flatpak remote (check mode)
|
||||
flatpak_remote:
|
||||
name: check-mode-test-remote
|
||||
state: absent
|
||||
register: double_removal_result
|
||||
check_mode: true
|
||||
|
||||
- name: >
|
||||
Verify non-existent idempotency of removal of present flatpak remote
|
||||
test result (check mode)
|
||||
assert:
|
||||
that:
|
||||
- "double_removal_result.changed == true"
|
||||
msg: |
|
||||
Removing a present flatpak remote a second time shall still mark module execution
|
||||
as changed in check mode
|
|
@ -0,0 +1,57 @@
|
|||
# (c) 2018, Alexander Bethke <oolongbrothers@gmx.net>
|
||||
# (c) 2018, Ansible Project
|
||||
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
- block:
|
||||
|
||||
- import_tasks: setup.yml
|
||||
become: true
|
||||
|
||||
# executable override
|
||||
|
||||
- name: Test executable override
|
||||
flatpak_remote:
|
||||
name: irrelevant
|
||||
remote: irrelevant
|
||||
state: present
|
||||
executable: nothing-that-exists
|
||||
ignore_errors: true
|
||||
register: executable_override_result
|
||||
|
||||
- name: Verify executable override test result
|
||||
assert:
|
||||
that:
|
||||
- "executable_override_result.failed == true"
|
||||
- "executable_override_result.changed == false"
|
||||
msg: "Specifying non-existing executable shall fail module execution"
|
||||
|
||||
- import_tasks: check_mode.yml
|
||||
become: false
|
||||
|
||||
- import_tasks: test.yml
|
||||
become: false
|
||||
vars:
|
||||
method: user
|
||||
|
||||
- import_tasks: test.yml
|
||||
become: true
|
||||
vars:
|
||||
method: system
|
||||
|
||||
when: |
|
||||
ansible_distribution == 'Fedora' or
|
||||
ansible_distribution == 'Ubuntu' and not ansible_distribution_major_version | int < 16
|
|
@ -0,0 +1,27 @@
|
|||
- name: Install flatpak on Fedora
|
||||
dnf:
|
||||
name: flatpak
|
||||
state: present
|
||||
|
||||
when: ansible_distribution == 'Fedora'
|
||||
|
||||
- block:
|
||||
- name: Activate flatpak ppa on Ubuntu versions older than 18.04/bionic
|
||||
apt_repository:
|
||||
repo: "ppa:alexlarsson/flatpak"
|
||||
state: present
|
||||
mode: 0644
|
||||
when: ansible_lsb.major_release | int < 18
|
||||
|
||||
- name: Install flatpak package on Ubuntu
|
||||
apt:
|
||||
name: flatpak
|
||||
state: present
|
||||
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
|
||||
- name: Install flatpak remote for testing check mode
|
||||
flatpak_remote:
|
||||
name: check-mode-test-remote
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
|
@ -0,0 +1,72 @@
|
|||
# state=present
|
||||
|
||||
- name: Test addition - {{ method }}
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
||||
method: "{{ method }}"
|
||||
register: addition_result
|
||||
|
||||
- name: Verify addition test result - {{ method }}
|
||||
assert:
|
||||
that:
|
||||
- "addition_result.changed == true"
|
||||
msg: "state=preset shall add flatpak when absent"
|
||||
|
||||
- name: Test idempotency of addition - {{ method }}
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
state: present
|
||||
method: "{{ method }}"
|
||||
register: double_addition_result
|
||||
|
||||
- name: Verify idempotency of addition test result - {{ method }}
|
||||
assert:
|
||||
that:
|
||||
- "double_addition_result.changed == false"
|
||||
msg: "state=present shall not do anything when flatpak is already present"
|
||||
|
||||
- name: Test updating remote url does not do anything - {{ method }}
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
flatpakrepo_url: https://a.different/repo.flatpakrepo
|
||||
state: present
|
||||
method: "{{ method }}"
|
||||
register: url_update_result
|
||||
|
||||
- name: Verify updating remote url does not do anything - {{ method }}
|
||||
assert:
|
||||
that:
|
||||
- "url_update_result.changed == false"
|
||||
msg: "Trying to update the URL of an existing flatpak remote shall not do anything"
|
||||
|
||||
|
||||
# state=absent
|
||||
|
||||
- name: Test removal - {{ method }}
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
state: absent
|
||||
method: "{{ method }}"
|
||||
register: removal_result
|
||||
|
||||
- name: Verify removal test result - {{ method }}
|
||||
assert:
|
||||
that:
|
||||
- "removal_result.changed == true"
|
||||
msg: "state=absent shall remove flatpak when present"
|
||||
|
||||
- name: Test idempotency of removal - {{ method }}
|
||||
flatpak_remote:
|
||||
name: flatpak-test
|
||||
state: absent
|
||||
method: "{{ method }}"
|
||||
register: double_removal_result
|
||||
|
||||
- name: Verify idempotency of removal test result - {{ method }}
|
||||
assert:
|
||||
that:
|
||||
- "double_removal_result.changed == false"
|
||||
msg: "state=absent shall not do anything when flatpak is not present"
|
|
@ -0,0 +1,11 @@
|
|||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
destructive
|
||||
skip/docker # The tests sometimes make docker daemon unstable; hence,
|
||||
# we skip all docker-based CI runs to avoid disrupting
|
||||
# the whole CI system. On VMs, we restart docker daemon
|
||||
# after finishing the tests to minimize potential effects
|
||||
# on other tests.
|
||||
needs/root
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
plugin: docker_swarm
|
||||
docker_host: unix://var/run/docker.sock
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
plugin: docker_swarm
|
||||
docker_host: unix://var/run/docker.sock
|
||||
verbose_output: no
|
||||
include_host_uri: yes
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
dependencies:
|
||||
- incidental_setup_docker
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
- hosts: 127.0.0.1
|
||||
connection: local
|
||||
gather_facts: yes
|
||||
tasks:
|
||||
- name: Make sure swarm is removed
|
||||
docker_swarm:
|
||||
state: absent
|
||||
force: yes
|
||||
|
||||
- name: remove docker pagkages
|
||||
action: "{{ ansible_facts.pkg_mgr }}"
|
||||
args:
|
||||
name:
|
||||
- docker
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
state: absent
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
- hosts: 127.0.0.1
|
||||
connection: local
|
||||
vars:
|
||||
docker_skip_cleanup: yes
|
||||
|
||||
tasks:
|
||||
- name: Setup docker
|
||||
import_role:
|
||||
name: incidental_setup_docker
|
||||
|
||||
- name: Create a Swarm cluster
|
||||
docker_swarm:
|
||||
state: present
|
||||
advertise_addr: "{{ansible_default_ipv4.address | default('127.0.0.1')}}"
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
- hosts: 127.0.0.1
|
||||
connection: local # otherwise Ansible will complain that it cannot connect via ssh to 127.0.0.1:22
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Show all groups
|
||||
debug:
|
||||
var: groups
|
||||
- name: Make sure docker_swarm groups are there
|
||||
assert:
|
||||
that:
|
||||
- groups.all | length > 0
|
||||
- groups.leader | length == 1
|
||||
- groups.manager | length > 0
|
||||
- groups.worker | length >= 0
|
||||
- groups.nonleaders | length >= 0
|
||||
|
||||
- hosts: all
|
||||
connection: local # otherwise Ansible will complain that it cannot connect via ssh to 127.0.0.1:22
|
||||
vars:
|
||||
# for some reason, Ansible can't find the Python interpreter when connecting to the nodes,
|
||||
# which is in fact just localhost in disguise. That's why we use ansible_playbook_python.
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
tasks:
|
||||
- name: Check for groups
|
||||
assert:
|
||||
that:
|
||||
- "groups.manager | length > 0"
|
||||
- "groups.worker | length >= 0"
|
||||
- "groups.leader | length == 1"
|
||||
run_once: yes
|
||||
|
||||
- name: List manager group
|
||||
debug:
|
||||
var: groups.manager
|
||||
run_once: yes
|
||||
|
||||
- name: List worker group
|
||||
debug:
|
||||
var: groups.worker
|
||||
run_once: yes
|
||||
|
||||
- name: List leader group
|
||||
debug:
|
||||
var: groups.leader
|
||||
run_once: yes
|
||||
|
||||
- name: Print ansible_host per host
|
||||
debug:
|
||||
var: ansible_host
|
||||
|
||||
- name: Make sure docker_swarm_node_attributes is available
|
||||
assert:
|
||||
that:
|
||||
- docker_swarm_node_attributes is not undefined
|
||||
- name: Print docker_swarm_node_attributes per host
|
||||
debug:
|
||||
var: docker_swarm_node_attributes
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
- hosts: 127.0.0.1
|
||||
connection: local # otherwise Ansible will complain that it cannot connect via ssh to 127.0.0.1:22
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Show all groups
|
||||
debug:
|
||||
var: groups
|
||||
- name: Make sure docker_swarm groups are there
|
||||
assert:
|
||||
that:
|
||||
- groups.all | length > 0
|
||||
- groups.leader | length == 1
|
||||
- groups.manager | length > 0
|
||||
- groups.worker | length >= 0
|
||||
- groups.nonleaders | length >= 0
|
||||
|
||||
- hosts: all
|
||||
connection: local # otherwise Ansible will complain that it cannot connect via ssh to 127.0.0.1:22
|
||||
vars:
|
||||
# for some reason, Ansible can't find the Python interpreter when connecting to the nodes,
|
||||
# which is in fact just localhost in disguise. That's why we use ansible_playbook_python.
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
tasks:
|
||||
- name: Make sure docker_swarm_node_attributes is not available
|
||||
assert:
|
||||
that:
|
||||
- docker_swarm_node_attributes is undefined
|
||||
- name: Make sure ansible_host_uri is available
|
||||
assert:
|
||||
that:
|
||||
- ansible_host_uri is defined
|
||||
- name: Print ansible_host_uri
|
||||
debug:
|
||||
var: ansible_host_uri
|
23
test/integration/targets/incidental_inventory_docker_swarm/runme.sh
Executable file
23
test/integration/targets/incidental_inventory_docker_swarm/runme.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cleanup() {
|
||||
echo "Cleanup"
|
||||
ansible-playbook playbooks/swarm_cleanup.yml
|
||||
echo "Done"
|
||||
exit 0
|
||||
}
|
||||
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
echo "Setup"
|
||||
ANSIBLE_ROLES_PATH=.. ansible-playbook playbooks/swarm_setup.yml
|
||||
|
||||
echo "Test docker_swarm inventory 1"
|
||||
ansible-playbook -i inventory_1.docker_swarm.yml playbooks/test_inventory_1.yml
|
||||
|
||||
echo "Test docker_swarm inventory 2"
|
||||
ansible-playbook -i inventory_2.docker_swarm.yml playbooks/test_inventory_2.yml
|
|
@ -0,0 +1,6 @@
|
|||
shippable/posix/incidental
|
||||
destructive
|
||||
needs/target/incidental_setup_openssl
|
||||
needs/file/test/lib/ansible_test/_data/requirements/constraints.txt
|
||||
skip/aix
|
||||
skip/python2.6
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
vault_gen_path: 'gen/testproject'
|
||||
vault_kv1_path: 'kv1/testproject'
|
||||
vault_kv2_path: 'kv2/data/testproject'
|
|
@ -0,0 +1,21 @@
|
|||
- 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
|
|
@ -0,0 +1,45 @@
|
|||
- 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
|
|
@ -0,0 +1,155 @@
|
|||
---
|
||||
- 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 >/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
|
|
@ -0,0 +1,35 @@
|
|||
- 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 '
|
|
@ -0,0 +1,3 @@
|
|||
- name: 'Create a test credentials (token)'
|
||||
command: '{{ vault_cmd }} token create -policy test-policy -field token'
|
||||
register: user_token_cmd
|
|
@ -0,0 +1,58 @@
|
|||
- 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
|
|
@ -0,0 +1,10 @@
|
|||
# {{ 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 %}
|
|
@ -0,0 +1,19 @@
|
|||
- 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') }}"
|
|
@ -0,0 +1,9 @@
|
|||
- 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
|
23
test/integration/targets/incidental_lookup_hashi_vault/runme.sh
Executable file
23
test/integration/targets/incidental_lookup_hashi_vault/runme.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/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 <function _verify_callback at 0x106f995f0>:
|
||||
# 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 <class 'requests.exceptions.SSLError'>, 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 "$@"
|
|
@ -0,0 +1,6 @@
|
|||
destructive
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- incidental_setup_rabbitmq
|
|
@ -0,0 +1,5 @@
|
|||
# Rabbitmq lookup
|
||||
- include: ubuntu.yml
|
||||
when:
|
||||
- ansible_distribution == 'Ubuntu'
|
||||
- ansible_distribution_release != 'trusty'
|
|
@ -0,0 +1,138 @@
|
|||
- name: Test failure without pika installed
|
||||
set_fact:
|
||||
rabbit_missing_pika: "{{ lookup('rabbitmq', url='amqp://guest:guest@192.168.250.1:5672/%2F', queue='hello', count=3) }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_missing_pika_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "'pika python package is required' in rabbitmq_missing_pika_error.msg"
|
||||
|
||||
- name: Install pika and requests
|
||||
pip:
|
||||
name: pika<1.0.0,requests
|
||||
state: latest
|
||||
|
||||
- name: Test that giving an incorrect amqp protocol in URL will error
|
||||
set_fact:
|
||||
rabbitmq_test_protocol: "{{ lookup('rabbitmq', url='zzzamqp://guest:guest@192.168.250.1:5672/%2F', queue='hello', count=3) }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_protocol_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "rabbitmq_protocol_error is failed"
|
||||
- "'URL malformed' in rabbitmq_protocol_error.msg"
|
||||
|
||||
- name: Test that giving an incorrect IP address in URL will error
|
||||
set_fact:
|
||||
rabbitmq_test_protocol: "{{ lookup('rabbitmq', url='amqp://guest:guest@xxxxx192.112312368.250.1:5672/%2F', queue='hello', count=3) }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_ip_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "rabbitmq_ip_error is failed"
|
||||
- "'Connection issue' in rabbitmq_ip_error.msg"
|
||||
|
||||
- name: Test missing parameters will error
|
||||
set_fact:
|
||||
rabbitmq_test_protocol: "{{ lookup('rabbitmq') }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_params_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "rabbitmq_params_error is failed"
|
||||
- "'URL is required for rabbitmq lookup.' in rabbitmq_params_error.msg"
|
||||
|
||||
- name: Test missing queue will error
|
||||
set_fact:
|
||||
rabbitmq_queue_protocol: "{{ lookup('rabbitmq', url='amqp://guest:guest@192.168.250.1:5672/%2F') }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_queue_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "rabbitmq_queue_error is failed"
|
||||
- "'Queue is required for rabbitmq lookup' in rabbitmq_queue_error.msg"
|
||||
|
||||
- name: Enables the rabbitmq_management plugin
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management
|
||||
state: enabled
|
||||
|
||||
- name: Setup test queue
|
||||
rabbitmq_queue:
|
||||
name: hello
|
||||
|
||||
- name: Post test message to the exchange (string)
|
||||
uri:
|
||||
url: http://localhost:15672/api/exchanges/%2f/amq.default/publish
|
||||
method: POST
|
||||
body: '{"properties":{},"routing_key":"hello","payload":"ansible-test","payload_encoding":"string"}'
|
||||
user: guest
|
||||
password: guest
|
||||
force_basic_auth: yes
|
||||
return_content: yes
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
register: post_data
|
||||
|
||||
|
||||
- name: Post test message to the exchange (json)
|
||||
uri:
|
||||
url: http://localhost:15672/api/exchanges/%2f/amq.default/publish
|
||||
method: POST
|
||||
body: '{"properties":{"content_type": "application/json"},"routing_key":"hello","payload":"{\"key\": \"value\" }","payload_encoding":"string"}'
|
||||
user: guest
|
||||
password: guest
|
||||
force_basic_auth: yes
|
||||
return_content: yes
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
register: post_data_json
|
||||
|
||||
- name: Test retrieve messages
|
||||
set_fact:
|
||||
rabbitmq_msg: "{{ lookup('rabbitmq', url='amqp://guest:guest@localhost:5672/%2f/hello', queue='hello') }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_msg_error
|
||||
|
||||
- name: Ensure two messages received
|
||||
assert:
|
||||
that:
|
||||
- "rabbitmq_msg_error is not failed"
|
||||
- rabbitmq_msg | length == 2
|
||||
|
||||
- name: Ensure first message is a string
|
||||
assert:
|
||||
that:
|
||||
- rabbitmq_msg[0].msg == "ansible-test"
|
||||
|
||||
- name: Ensure second message is json
|
||||
assert:
|
||||
that:
|
||||
- rabbitmq_msg[1].json.key == "value"
|
||||
|
||||
- name: Test missing vhost
|
||||
set_fact:
|
||||
rabbitmq_msg: "{{ lookup('rabbitmq', url='amqp://guest:guest@localhost:5672/missing/', queue='hello') }}"
|
||||
ignore_errors: yes
|
||||
register: rabbitmq_vhost_error
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "rabbitmq_vhost_error is failed"
|
||||
- "'NOT_ALLOWED' in rabbitmq_vhost_error.msg"
|
||||
|
||||
# Tidy up
|
||||
- name: Uninstall pika and requests
|
||||
pip:
|
||||
name: pika,requests
|
||||
state: absent
|
||||
|
||||
- name: Disable the rabbitmq_management plugin
|
||||
rabbitmq_plugin:
|
||||
names: rabbitmq_management
|
||||
state: disabled
|
6
test/integration/targets/incidental_lvg/aliases
Normal file
6
test/integration/targets/incidental_lvg/aliases
Normal file
|
@ -0,0 +1,6 @@
|
|||
destructive
|
||||
needs/privileged
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/osx
|
2
test/integration/targets/incidental_lvg/meta/main.yml
Normal file
2
test/integration/targets/incidental_lvg/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- setup_remote_tmp_dir
|
15
test/integration/targets/incidental_lvg/tasks/main.yml
Normal file
15
test/integration/targets/incidental_lvg/tasks/main.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
- name: Install required packages (Linux)
|
||||
package:
|
||||
name: lvm2
|
||||
state: present
|
||||
when: ansible_system == 'Linux'
|
||||
|
||||
- name: Test lvg module
|
||||
block:
|
||||
- import_tasks: setup.yml
|
||||
|
||||
- import_tasks: test_indempotency.yml
|
||||
|
||||
- import_tasks: test_grow_reduce.yml
|
||||
always:
|
||||
- import_tasks: teardown.yml
|
13
test/integration/targets/incidental_lvg/tasks/setup.yml
Normal file
13
test/integration/targets/incidental_lvg/tasks/setup.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
- name: "Create files to use as a disk devices"
|
||||
command: "dd if=/dev/zero of={{ remote_tmp_dir }}/img{{ item }} bs=1M count=10"
|
||||
with_sequence: 'count=2'
|
||||
|
||||
- name: "Create loop device for file"
|
||||
command: "losetup --show -f {{ remote_tmp_dir }}/img{{ item }}"
|
||||
with_sequence: 'count=2'
|
||||
register: loop_devices
|
||||
|
||||
- name: "Affect name on disk to work on"
|
||||
set_fact:
|
||||
loop_device1: "{{ loop_devices.results[0] }}"
|
||||
loop_device2: "{{ loop_devices.results[1] }}"
|
17
test/integration/targets/incidental_lvg/tasks/teardown.yml
Normal file
17
test/integration/targets/incidental_lvg/tasks/teardown.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
- name: Remove test volume group
|
||||
lvg:
|
||||
vg: testvg
|
||||
state: absent
|
||||
|
||||
- name: Detach loop device
|
||||
command: "losetup -d {{ item.stdout }}"
|
||||
loop: "{{ loop_devices.results|default([]) }}"
|
||||
when:
|
||||
- item.stdout is defined
|
||||
- item.stdout is match("/dev/.*")
|
||||
|
||||
- name: Remove device files
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/img{{ item }}"
|
||||
state: absent
|
||||
with_sequence: 'count={{ loop_devices.results|length }}'
|
|
@ -0,0 +1,33 @@
|
|||
- name: "Create volume group on first disk"
|
||||
lvg:
|
||||
vg: testvg
|
||||
pvs: "{{ loop_device1.stdout }}"
|
||||
|
||||
- name: "get lvm facts"
|
||||
setup:
|
||||
|
||||
- debug: var=ansible_lvm
|
||||
|
||||
- name: "Assert the testvg span only on first disk"
|
||||
assert:
|
||||
that:
|
||||
- ansible_lvm.pvs[loop_device1.stdout].vg == "testvg"
|
||||
- 'loop_device2.stdout not in ansible_lvm.pvs or
|
||||
ansible_lvm.pvs[loop_device2.stdout].vg == ""'
|
||||
|
||||
- name: "Extend to second disk AND reduce from the first disk"
|
||||
lvg:
|
||||
vg: testvg
|
||||
pvs: "{{ loop_device2.stdout }}"
|
||||
|
||||
- name: "get lvm facts"
|
||||
setup:
|
||||
|
||||
- debug: var=ansible_lvm
|
||||
|
||||
- name: "Assert the testvg span only on first disk"
|
||||
assert:
|
||||
that:
|
||||
- 'loop_device1.stdout not in ansible_lvm.pvs or
|
||||
ansible_lvm.pvs[loop_device1.stdout].vg == ""'
|
||||
- ansible_lvm.pvs[loop_device2.stdout].vg == "testvg"
|
|
@ -0,0 +1,15 @@
|
|||
- name: Create volume group on disk device
|
||||
lvg:
|
||||
vg: testvg
|
||||
pvs: "{{ loop_device1.stdout }}"
|
||||
|
||||
- name: Create the volume group again to verify idempotence
|
||||
lvg:
|
||||
vg: testvg
|
||||
pvs: "{{ loop_device1.stdout }}"
|
||||
register: repeat_vg_create
|
||||
|
||||
- name: Do all assertions to verify expected results
|
||||
assert:
|
||||
that:
|
||||
- repeat_vg_create is not changed
|
|
@ -0,0 +1,7 @@
|
|||
destructive
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
||||
needs/root
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# defaults file for test_mongodb_user
|
||||
mongodb_admin_user: test_root
|
||||
mongodb_admin_password: saE_Rr9!gE6gh#e~R#nZ
|
||||
mongod_auth: false
|
||||
kill_signal: SIGTERM
|
||||
# Should be one of
|
||||
# --storageEngine wiredTiger --wiredTigerEngineConfigString="cache_size=200M"
|
||||
# --storageEngine mmapv1 --nojournal
|
||||
mongod_storage_engine_opts: "--storageEngine wiredTiger --wiredTigerEngineConfigString='cache_size=200M'"
|
||||
mongodb_user: mongodb
|
||||
mongodb_user_list:
|
||||
- { "name": "user1", "password": "password1", "roles": "read", "database": "test" }
|
||||
- { "name": "user2", "password": "password2", "roles": "readWrite", "database": "test" }
|
||||
- { "name": "user3", "password": "password3", "roles": "dbAdmin", "database": "test" }
|
||||
- { "name": "user4", "password": "password4", "roles": "userAdmin", "database": "test" }
|
||||
- { "name": "user5", "password": "password5", "roles": "clusterAdmin", "database": "admin" }
|
||||
- { "name": "user6", "password": "password6", "roles": "readAnyDatabase", "database": "admin" }
|
||||
- { "name": "user7", "password": "password7", "roles": "readWriteAnyDatabase", "database": "admin" }
|
||||
- { "name": "user8", "password": "password8", "roles": "userAdminAnyDatabase", "database": "admin" }
|
||||
- { "name": "user9", "password": "password9", "roles": "dbAdminAnyDatabase", "database": "admin" }
|
|
@ -0,0 +1,3 @@
|
|||
dependencies:
|
||||
- incidental_setup_mongodb
|
||||
- setup_remote_tmp_dir
|
|
@ -0,0 +1,143 @@
|
|||
# test code for the mongodb_parameter module
|
||||
# (c) 2019, Rhys Campbell <rhys.james.campbell@googlemail.com>
|
||||
|
||||
# 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 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
# ============================================================
|
||||
|
||||
- name: Ensure tests home exists
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/tests"
|
||||
state: directory
|
||||
|
||||
- include_tasks: mongod_teardown.yml
|
||||
|
||||
- include_tasks: mongod_singlenode.yml
|
||||
|
||||
- name: Set syncdelay to 99
|
||||
mongodb_parameter:
|
||||
login_port: 3001
|
||||
param: syncdelay
|
||||
value: 99
|
||||
param_type: int
|
||||
register: sd_change
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- sd_change.before | int == 60
|
||||
- sd_change.after | int == 99
|
||||
- sd_change.changed == True
|
||||
|
||||
- name: Set syncdelay to 99 (again)
|
||||
mongodb_parameter:
|
||||
login_port: 3001
|
||||
param: syncdelay
|
||||
value: 99
|
||||
param_type: int
|
||||
register: sd_change
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- sd_change.before | int == 99
|
||||
- sd_change.after | int == 99
|
||||
- sd_change.changed == False
|
||||
|
||||
- name: Create admin user with module
|
||||
mongodb_user:
|
||||
login_port: 3001
|
||||
database: admin
|
||||
name: "{{ mongodb_admin_user }}"
|
||||
password: "{{ mongodb_admin_password }}"
|
||||
roles: root
|
||||
state: present
|
||||
register: mongodb_admin_user_created
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mongodb_admin_user_created.changed == True
|
||||
|
||||
- name: Kill all mongod processes
|
||||
command: pkill -{{ kill_signal }} mongod
|
||||
ignore_errors: true
|
||||
|
||||
- name: Getting pids for mongod
|
||||
pids:
|
||||
name: mongod
|
||||
register: pids_of_mongod
|
||||
|
||||
- name: Wait for all mongod processes to exit
|
||||
wait_for:
|
||||
path: "/proc/{{ item }}/status"
|
||||
state: absent
|
||||
delay: 3
|
||||
with_items: "{{ pids_of_mongod }}"
|
||||
|
||||
- set_fact:
|
||||
mongod_auth: true
|
||||
|
||||
- include_tasks: mongod_singlenode.yml
|
||||
# Tests with auth enabled
|
||||
|
||||
- name: Set syncdelay to 59 with auth
|
||||
mongodb_parameter:
|
||||
login_port: 3001
|
||||
login_user: "{{ mongodb_admin_user }}"
|
||||
login_password: "{{ mongodb_admin_password }}"
|
||||
param: syncdelay
|
||||
value: 59
|
||||
param_type: int
|
||||
register: sd_change
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- sd_change.before | int == 60
|
||||
- sd_change.after | int == 59
|
||||
- sd_change.changed == True
|
||||
|
||||
- name: Set syncdelay to 59 (again) with auth
|
||||
mongodb_parameter:
|
||||
login_port: 3001
|
||||
login_user: "{{ mongodb_admin_user }}"
|
||||
login_password: "{{ mongodb_admin_password }}"
|
||||
param: syncdelay
|
||||
value: 59
|
||||
param_type: int
|
||||
register: sd_change
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- sd_change.before | int == 59
|
||||
- sd_change.after | int == 59
|
||||
- sd_change.changed == False
|
||||
|
||||
- name: Set authenticationMechanisms to MONGODB-X509 with auth (will fail)
|
||||
mongodb_parameter:
|
||||
login_port: 3001
|
||||
login_user: "{{ mongodb_admin_user }}"
|
||||
login_password: "{{ mongodb_admin_password }}"
|
||||
param: authenticationMechanisms
|
||||
value: "MONGODB-X509"
|
||||
param_type: str
|
||||
register: diag_change
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- '"unable to change parameter" in diag_change.msg'
|
||||
- diag_change.failed == True
|
||||
|
||||
# Clean up
|
||||
- include_tasks: mongod_teardown.yml
|
|
@ -0,0 +1,55 @@
|
|||
- name: Set mongodb_user user for redhat
|
||||
set_fact:
|
||||
mongodb_user: "mongod"
|
||||
when: ansible_os_family == "RedHat"
|
||||
|
||||
- set_fact:
|
||||
mongodb_nodes:
|
||||
- 3001
|
||||
|
||||
- name: Create directories for mongod processes
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/mongod{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ mongodb_user }}"
|
||||
group: "{{ mongodb_user }}"
|
||||
mode: 0755
|
||||
recurse: yes
|
||||
with_items: "{{ mongodb_nodes }}"
|
||||
|
||||
- name: Ensure {{ remote_tmp_dir }}/config dir exists
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/config"
|
||||
state: directory
|
||||
owner: "{{ mongodb_user }}"
|
||||
group: "{{ mongodb_user }}"
|
||||
mode: 0755
|
||||
|
||||
- name: Create keyfile
|
||||
copy:
|
||||
dest: "{{ remote_tmp_dir }}/my.key"
|
||||
content: |
|
||||
fd2CUrbXBJpB4rt74A6F
|
||||
owner: "{{ mongodb_user }}"
|
||||
group: "{{ mongodb_user }}"
|
||||
mode: 0600
|
||||
when: mongod_auth == True
|
||||
|
||||
- name: Spawn mongod process without auth
|
||||
command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --logpath mongod{{ item }}/log.log --fork
|
||||
args:
|
||||
chdir: "{{ remote_tmp_dir }}"
|
||||
with_items: "{{ mongodb_nodes | sort }}"
|
||||
when: mongod_auth == False
|
||||
|
||||
- name: Spawn mongod process with auth
|
||||
command: mongod --shardsvr --smallfiles {{ mongod_storage_engine_opts }} --dbpath mongod{{ item }} --port {{ item }} --logpath mongod{{ item }}/log.log --fork --auth --keyFile my.key
|
||||
args:
|
||||
chdir: "{{ remote_tmp_dir }}"
|
||||
with_items: "{{ mongodb_nodes | sort }}"
|
||||
when: mongod_auth == True
|
||||
|
||||
- name: Wait for mongod to start responding
|
||||
wait_for:
|
||||
port: "{{ item }}"
|
||||
with_items: "{{ mongodb_nodes }}"
|
|
@ -0,0 +1,25 @@
|
|||
- name: Kill all mongod processes
|
||||
command: pkill -{{ kill_signal }} mongod
|
||||
ignore_errors: true
|
||||
|
||||
- name: Getting pids for mongod
|
||||
pids:
|
||||
name: mongod
|
||||
register: pids_of_mongod
|
||||
|
||||
- name: Wait for all mongod processes to exit
|
||||
wait_for:
|
||||
path: "/proc/{{ item }}/status"
|
||||
state: absent
|
||||
delay: 1
|
||||
with_items: "{{ pids_of_mongod }}"
|
||||
|
||||
- name: Remove all mongod folders
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- mongod3001
|
||||
|
||||
- name: Remove all mongod sock files
|
||||
shell: rm -Rf /tmp/mongodb*.sock
|
|
@ -0,0 +1,4 @@
|
|||
destructive
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
||||
skip/osx
|
|
@ -0,0 +1,3 @@
|
|||
db_name: 'ansible_db'
|
||||
db_user1: 'ansible_db_user1'
|
||||
db_user2: 'ansible_db_user2'
|
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- incidental_setup_postgresql_db
|
|
@ -0,0 +1,7 @@
|
|||
# Initial CI tests of postgresql_user module
|
||||
- import_tasks: postgresql_user_initial.yml
|
||||
when: postgres_version_resp.stdout is version('9.4', '>=')
|
||||
|
||||
# General tests:
|
||||
- import_tasks: postgresql_user_general.yml
|
||||
when: postgres_version_resp.stdout is version('9.4', '>=')
|
|
@ -0,0 +1,741 @@
|
|||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# Integration tests for postgresql_user module.
|
||||
|
||||
- vars:
|
||||
test_user: hello.user.with.dots
|
||||
test_user2: hello
|
||||
test_group1: group1
|
||||
test_group2: group2
|
||||
test_table: test
|
||||
test_comment1: 'comment1'
|
||||
test_comment2: 'comment2'
|
||||
task_parameters: &task_parameters
|
||||
become_user: '{{ pg_user }}'
|
||||
become: yes
|
||||
register: result
|
||||
pg_parameters: &pg_parameters
|
||||
login_user: '{{ pg_user }}'
|
||||
login_db: postgres
|
||||
|
||||
block:
|
||||
#
|
||||
# Common tests
|
||||
#
|
||||
- name: Create role in check_mode
|
||||
<<: *task_parameters
|
||||
check_mode: yes
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user doesn't exist
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 0
|
||||
|
||||
- name: Create role in actual mode
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user exists
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Add a comment on the user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
comment: '{{ test_comment1 }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.queries == ["COMMENT ON ROLE \"{{ test_user }}\" IS '{{ test_comment1 }}'"]
|
||||
|
||||
- name: check the comment
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT pg_catalog.shobj_description(r.oid, 'pg_authid') AS comment
|
||||
FROM pg_catalog.pg_roles r WHERE r.rolname = '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
- result.query_result[0].comment == '{{ test_comment1 }}'
|
||||
|
||||
- name: Try to add the same comment on the user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
comment: '{{ test_comment1 }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: Try to add another comment on the user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
comment: '{{ test_comment2 }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.queries == ["COMMENT ON ROLE \"{{ test_user }}\" IS '{{ test_comment2 }}'"]
|
||||
|
||||
- name: check the comment
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT pg_catalog.shobj_description(r.oid, 'pg_authid') AS comment
|
||||
FROM pg_catalog.pg_roles r WHERE r.rolname = '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
- result.query_result[0].comment == '{{ test_comment2 }}'
|
||||
|
||||
- name: Try to create role again in check_mode
|
||||
<<: *task_parameters
|
||||
check_mode: yes
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user exists
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Try to create role again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user exists
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Drop role in check_mode
|
||||
<<: *task_parameters
|
||||
check_mode: yes
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user actually exists
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Drop role in actual mode
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: check that the user doesn't exist
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_user }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 0
|
||||
|
||||
- name: Try to drop role in check mode again
|
||||
<<: *task_parameters
|
||||
check_mode: yes
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Try to drop role in actual mode again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
state: absent
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
#
|
||||
# password, no_password_changes, encrypted, expires parameters
|
||||
#
|
||||
|
||||
- name: Create role with password, passed as hashed md5
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
password: md59543f1d82624df2b31672ec0f7050460
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check that the user exist with a proper password
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}' and rolpassword = 'md59543f1d82624df2b31672ec0f7050460'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Test no_password_changes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
password: u123
|
||||
no_password_changes: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
|
||||
- name: Check that nothing changed
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}' and rolpassword = 'md59543f1d82624df2b31672ec0f7050460'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
# Storing unencrypted passwords is not available from PostgreSQL 10
|
||||
- name: Change password, passed as unencrypted
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
password: myunencryptedpass
|
||||
encrypted: no
|
||||
when: postgres_version_resp.stdout is version('10', '<')
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
when: postgres_version_resp.stdout is version('10', '<')
|
||||
|
||||
- name: Check that the user exist with the unencrypted password
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}' and rolpassword = 'myunencryptedpass'"
|
||||
when: postgres_version_resp.stdout is version('10', '<')
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
when: postgres_version_resp.stdout is version('10', '<')
|
||||
|
||||
- name: Change password, explicit encrypted=yes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
password: myunencryptedpass
|
||||
encrypted: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check that the user exist with encrypted password
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}' and rolpassword != 'myunencryptedpass'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Change rolvaliduntil attribute
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
expires: 'Jan 31 2020'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check the prev step
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolvaliduntil::text like '2020-01-31%'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Try to set the same rolvaliduntil value again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
expires: 'Jan 31 2020'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check that nothing changed
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolvaliduntil::text like '2020-01-31%'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
#
|
||||
# role_attr_flags
|
||||
#
|
||||
- name: Set role attributes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
role_attr_flags: CREATEROLE,CREATEDB
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check the prev step
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolcreaterole = 't' and rolcreatedb = 't'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Set the same role attributes again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
role_attr_flags: CREATEROLE,CREATEDB
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check the prev step
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolcreaterole = 't' and rolcreatedb = 't'
|
||||
|
||||
- name: Set role attributes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
role_attr_flags: NOCREATEROLE,NOCREATEDB
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check the prev step
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolcreaterole = 'f' and rolcreatedb = 'f'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Set role attributes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
role_attr_flags: NOCREATEROLE,NOCREATEDB
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_user }}'
|
||||
|
||||
- name: Check the prev step
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: >
|
||||
SELECT rolname FROM pg_authid WHERE rolname = '{{ test_user }}'
|
||||
AND rolcreaterole = 'f' and rolcreatedb = 'f'
|
||||
|
||||
#
|
||||
# priv
|
||||
#
|
||||
- name: Create test table
|
||||
<<: *task_parameters
|
||||
postgresql_table:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_table }}'
|
||||
columns:
|
||||
- id int
|
||||
|
||||
- name: Insert data to test table
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
query: "INSERT INTO {{ test_table }} (id) VALUES ('1')"
|
||||
<<: *pg_parameters
|
||||
|
||||
- name: Check that test_user is not allowed to read the data
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
db: postgres
|
||||
login_user: '{{ pg_user }}'
|
||||
session_role: '{{ test_user }}'
|
||||
query: 'SELECT * FROM {{ test_table }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is failed
|
||||
- "'permission denied' in result.msg"
|
||||
|
||||
- name: Grant privileges
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
priv: '{{ test_table }}:SELECT'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Check that test_user is allowed to read the data
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
db: postgres
|
||||
login_user: '{{ pg_user }}'
|
||||
session_role: '{{ test_user }}'
|
||||
query: 'SELECT * FROM {{ test_table }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Grant the same privileges again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
priv: '{{ test_table }}:SELECT'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: Remove test table
|
||||
<<: *task_parameters
|
||||
postgresql_table:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_table }}'
|
||||
state: absent
|
||||
|
||||
#
|
||||
# fail_on_user
|
||||
#
|
||||
- name: Create role for test
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user2 }}'
|
||||
|
||||
- name: Create test table, set owner as test_user
|
||||
<<: *task_parameters
|
||||
postgresql_table:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_table }}'
|
||||
owner: '{{ test_user2 }}'
|
||||
|
||||
- name: Test fail_on_user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user2 }}'
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is failed
|
||||
- result.msg == 'Unable to remove user'
|
||||
|
||||
- name: Test fail_on_user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
fail_on_user: no
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
#
|
||||
# Test groups parameter
|
||||
#
|
||||
- name: Create test group
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_group2 }}'
|
||||
role_attr_flags: NOLOGIN
|
||||
|
||||
- name: Create role test_group1 and grant test_group2 to test_group1 in check_mode
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_group1 }}'
|
||||
groups: '{{ test_group2 }}'
|
||||
role_attr_flags: NOLOGIN
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_group1 }}'
|
||||
- result.queries == ['CREATE USER "{{ test_group1 }}" NOLOGIN', 'GRANT "{{ test_group2 }}" TO "{{ test_group1 }}"']
|
||||
|
||||
- name: check that the user doesn't exist
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_group1 }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 0
|
||||
|
||||
- name: check membership
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT grolist FROM pg_group WHERE groname = '{{ test_group2 }}' AND grolist != '{}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 0
|
||||
|
||||
- name: Create role test_group1 and grant test_group2 to test_group1
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_group1 }}'
|
||||
groups: '{{ test_group2 }}'
|
||||
role_attr_flags: NOLOGIN
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_group1 }}'
|
||||
- result.queries == ['CREATE USER "{{ test_group1 }}" NOLOGIN', 'GRANT "{{ test_group2 }}" TO "{{ test_group1 }}"']
|
||||
|
||||
- name: check that the user exists
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT rolname FROM pg_roles WHERE rolname = '{{ test_group1 }}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: check membership
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT grolist FROM pg_group WHERE groname = '{{ test_group2 }}' AND grolist != '{}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Grant test_group2 to test_group1 again
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_group1 }}'
|
||||
groups: '{{ test_group2 }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result.user == '{{ test_group1 }}'
|
||||
|
||||
- name: check membership
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT grolist FROM pg_group WHERE groname = '{{ test_group2 }}' AND grolist != '{}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 1
|
||||
|
||||
- name: Grant groups to existent role
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_user }}'
|
||||
groups:
|
||||
- '{{ test_group1 }}'
|
||||
- '{{ test_group2 }}'
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.user == '{{ test_user }}'
|
||||
- result.queries == ['GRANT "{{ test_group1 }}" TO "{{ test_user }}"', 'GRANT "{{ test_group2 }}" TO "{{ test_user }}"']
|
||||
|
||||
- name: check membership
|
||||
<<: *task_parameters
|
||||
postgresql_query:
|
||||
<<: *pg_parameters
|
||||
query: "SELECT * FROM pg_group WHERE groname in ('{{ test_group1 }}', '{{ test_group2 }}') AND grolist != '{}'"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.rowcount == 2
|
||||
|
||||
always:
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
- name: Drop test table
|
||||
<<: *task_parameters
|
||||
postgresql_table:
|
||||
<<: *pg_parameters
|
||||
name: '{{ test_table }}'
|
||||
state: absent
|
||||
|
||||
- name: Drop test user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *pg_parameters
|
||||
name: '{{ item }}'
|
||||
state: absent
|
||||
loop:
|
||||
- '{{ test_user }}'
|
||||
- '{{ test_user2 }}'
|
||||
- '{{ test_group1 }}'
|
||||
- '{{ test_group2 }}'
|
|
@ -0,0 +1,153 @@
|
|||
#
|
||||
# Create and destroy user, test 'password' and 'encrypted' parameters
|
||||
#
|
||||
# unencrypted values are not supported on newer versions
|
||||
# do not run the encrypted: no tests if on 10+
|
||||
- set_fact:
|
||||
encryption_values:
|
||||
- 'yes'
|
||||
|
||||
- set_fact:
|
||||
encryption_values: '{{ encryption_values + ["no"]}}'
|
||||
when: postgres_version_resp.stdout is version('10', '<=')
|
||||
|
||||
- include_tasks: test_password.yml
|
||||
vars:
|
||||
encrypted: '{{ loop_item }}'
|
||||
db_password1: 'secretù' # use UTF-8
|
||||
loop: '{{ encryption_values }}'
|
||||
loop_control:
|
||||
loop_var: loop_item
|
||||
|
||||
# BYPASSRLS role attribute was introduced in PostgreSQL 9.5, so
|
||||
# we want to test attribute management differently depending
|
||||
# on the version.
|
||||
- set_fact:
|
||||
bypassrls_supported: "{{ postgres_version_resp.stdout is version('9.5.0', '>=') }}"
|
||||
|
||||
# test 'no_password_change' and 'role_attr_flags' parameters
|
||||
- include_tasks: test_no_password_change.yml
|
||||
vars:
|
||||
no_password_changes: '{{ loop_item }}'
|
||||
loop:
|
||||
- 'yes'
|
||||
- 'no'
|
||||
loop_control:
|
||||
loop_var: loop_item
|
||||
|
||||
### TODO: fail_on_user
|
||||
|
||||
#
|
||||
# Test login_user functionality
|
||||
#
|
||||
- name: Create a user to test login module parameters
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
postgresql_user:
|
||||
name: "{{ db_user1 }}"
|
||||
state: "present"
|
||||
encrypted: 'yes'
|
||||
password: "password"
|
||||
role_attr_flags: "CREATEDB,LOGIN,CREATEROLE"
|
||||
login_user: "{{ pg_user }}"
|
||||
db: postgres
|
||||
|
||||
- name: Create db
|
||||
postgresql_db:
|
||||
name: "{{ db_name }}"
|
||||
state: "present"
|
||||
login_user: "{{ db_user1 }}"
|
||||
login_password: "password"
|
||||
login_host: "localhost"
|
||||
|
||||
- name: Check that database created
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
|
||||
- name: Create a user
|
||||
postgresql_user:
|
||||
name: "{{ db_user2 }}"
|
||||
state: "present"
|
||||
encrypted: 'yes'
|
||||
password: "md55c8ccfd9d6711fc69a7eae647fc54f51"
|
||||
db: "{{ db_name }}"
|
||||
login_user: "{{ db_user1 }}"
|
||||
login_password: "password"
|
||||
login_host: "localhost"
|
||||
|
||||
- name: Check that it was created
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
shell: echo "select * from pg_user where usename='{{ db_user2 }}';" | psql -d postgres
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
|
||||
- name: Grant database privileges
|
||||
postgresql_privs:
|
||||
type: "database"
|
||||
state: "present"
|
||||
roles: "{{ db_user2 }}"
|
||||
privs: "CREATE,connect"
|
||||
objs: "{{ db_name }}"
|
||||
db: "{{ db_name }}"
|
||||
login: "{{ db_user1 }}"
|
||||
password: "password"
|
||||
host: "localhost"
|
||||
|
||||
- name: Check that the user has the requested permissions (database)
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
shell: echo "select datacl from pg_database where datname='{{ db_name }}';" | psql {{ db_name }}
|
||||
register: result_database
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result_database.stdout_lines[-1] == '(1 row)'"
|
||||
- "db_user2 ~ '=Cc' in result_database.stdout"
|
||||
|
||||
- name: Remove user
|
||||
postgresql_user:
|
||||
name: "{{ db_user2 }}"
|
||||
state: 'absent'
|
||||
priv: "ALL"
|
||||
db: "{{ db_name }}"
|
||||
login_user: "{{ db_user1 }}"
|
||||
login_password: "password"
|
||||
login_host: "localhost"
|
||||
|
||||
- name: Check that they were removed
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
shell: echo "select * from pg_user where usename='{{ db_user2 }}';" | psql -d postgres
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(0 rows)'"
|
||||
|
||||
- name: Destroy DB
|
||||
postgresql_db:
|
||||
state: absent
|
||||
name: "{{ db_name }}"
|
||||
login_user: "{{ db_user1 }}"
|
||||
login_password: "password"
|
||||
login_host: "localhost"
|
||||
|
||||
- name: Check that database was destroyed
|
||||
become: yes
|
||||
become_user: "{{ pg_user }}"
|
||||
shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(0 rows)'"
|
|
@ -0,0 +1,167 @@
|
|||
- vars:
|
||||
task_parameters: &task_parameters
|
||||
become_user: "{{ pg_user }}"
|
||||
become: yes
|
||||
register: result
|
||||
postgresql_parameters: ¶meters
|
||||
db: postgres
|
||||
name: "{{ db_user1 }}"
|
||||
login_user: "{{ pg_user }}"
|
||||
|
||||
block:
|
||||
|
||||
- name: Create a user with all role attributes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: "present"
|
||||
role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,LOGIN{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}"
|
||||
no_password_changes: '{{ no_password_changes }}' # no_password_changes is ignored when user doesn't already exist
|
||||
|
||||
- name: Check that the user has the requested role attributes
|
||||
<<: *task_parameters
|
||||
shell: "echo \"select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin {{ bypassrls_supported | ternary(\", 'bypassrls:'||rolbypassrls\", '') }} from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
- "'super:t' in result.stdout_lines[-2]"
|
||||
- "'createrole:t' in result.stdout_lines[-2]"
|
||||
- "'create:t' in result.stdout_lines[-2]"
|
||||
- "'inherit:t' in result.stdout_lines[-2]"
|
||||
- "'login:t' in result.stdout_lines[-2]"
|
||||
|
||||
- block:
|
||||
- name: Check that the user has the requested role attribute BYPASSRLS
|
||||
<<: *task_parameters
|
||||
shell: "echo \"select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "not bypassrls_supported or 'bypassrls:t' in result.stdout_lines[-2]"
|
||||
when: bypassrls_supported
|
||||
|
||||
- name: Modify a user to have no role attributes
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: "present"
|
||||
role_attr_flags: "NOSUPERUSER,NOCREATEROLE,NOCREATEDB,noinherit,NOLOGIN{{ bypassrls_supported | ternary(',NOBYPASSRLS', '') }}"
|
||||
no_password_changes: '{{ no_password_changes }}'
|
||||
|
||||
- name: Check that ansible reports it modified the role
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: "Check that the user doesn't have any attribute"
|
||||
<<: *task_parameters
|
||||
shell: "echo \"select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
- "'super:f' in result.stdout_lines[-2]"
|
||||
- "'createrole:f' in result.stdout_lines[-2]"
|
||||
- "'create:f' in result.stdout_lines[-2]"
|
||||
- "'inherit:f' in result.stdout_lines[-2]"
|
||||
- "'login:f' in result.stdout_lines[-2]"
|
||||
|
||||
- block:
|
||||
- name: Check that the user has the requested role attribute BYPASSRLS
|
||||
<<: *task_parameters
|
||||
shell: "echo \"select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "not bypassrls_supported or 'bypassrls:f' in result.stdout_lines[-2]"
|
||||
when: bypassrls_supported
|
||||
|
||||
- name: Try to add an invalid attribute
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: "present"
|
||||
role_attr_flags: "NOSUPERUSER,NOCREATEROLE,NOCREATEDB,noinherit,NOLOGIN{{ bypassrls_supported | ternary(',NOBYPASSRLS', '') }},INVALID"
|
||||
no_password_changes: '{{ no_password_changes }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check that ansible reports failure
|
||||
assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result is failed
|
||||
- "result.msg == 'Invalid role_attr_flags specified: INVALID'"
|
||||
|
||||
- name: Modify a single role attribute on a user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: "present"
|
||||
role_attr_flags: "LOGIN"
|
||||
no_password_changes: '{{ no_password_changes }}'
|
||||
|
||||
- name: Check that ansible reports it modified the role
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Check the role attributes
|
||||
<<: *task_parameters
|
||||
shell: echo "select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin from pg_roles where rolname='{{ db_user1 }}';" | psql -d postgres
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
- "'super:f' in result.stdout_lines[-2]"
|
||||
- "'createrole:f' in result.stdout_lines[-2]"
|
||||
- "'create:f' in result.stdout_lines[-2]"
|
||||
- "'inherit:f' in result.stdout_lines[-2]"
|
||||
- "'login:t' in result.stdout_lines[-2]"
|
||||
|
||||
- block:
|
||||
- name: Check the role attribute BYPASSRLS
|
||||
<<: *task_parameters
|
||||
shell: echo "select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';" | psql -d postgres
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "( postgres_version_resp.stdout is version('9.5.0', '<')) or 'bypassrls:f' in result.stdout_lines[-2]"
|
||||
when: bypassrls_supported
|
||||
|
||||
- name: Check that using same attribute a second time does nothing
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: "present"
|
||||
role_attr_flags: "LOGIN"
|
||||
no_password_changes: '{{ no_password_changes }}'
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- name: Check there isn't any update reported
|
||||
assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: Cleanup the user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: 'absent'
|
||||
no_password_changes: '{{ no_password_changes }}' # user deletion: no_password_changes is ignored
|
||||
|
||||
- name: Check that user was removed
|
||||
<<: *task_parameters
|
||||
shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(0 rows)'"
|
||||
|
||||
always:
|
||||
- name: Cleanup the user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
state: 'absent'
|
|
@ -0,0 +1,336 @@
|
|||
- vars:
|
||||
task_parameters: &task_parameters
|
||||
become_user: "{{ pg_user }}"
|
||||
become: yes
|
||||
register: result
|
||||
postgresql_parameters: ¶meters
|
||||
db: postgres
|
||||
name: "{{ db_user1 }}"
|
||||
login_user: "{{ pg_user }}"
|
||||
|
||||
block:
|
||||
- name: 'Check that PGOPTIONS environment variable is effective (1/2)'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: '{{ db_password1 }}'
|
||||
ignore_errors: true
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- name: 'Check that PGOPTIONS environment variable is effective (2/2)'
|
||||
assert:
|
||||
that:
|
||||
- "{{ result is failed }}"
|
||||
|
||||
- name: 'Create a user (password encrypted: {{ encrypted }})'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: '{{ db_password1 }}'
|
||||
encrypted: '{{ encrypted }}'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- block: &changed # block is only used here in order to be able to define YAML anchor
|
||||
- name: Check that ansible reports it was created
|
||||
assert:
|
||||
that:
|
||||
- "{{ result is changed }}"
|
||||
|
||||
- name: Check that it was created
|
||||
<<: *task_parameters
|
||||
shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(1 row)'"
|
||||
|
||||
- name: Check that creating user a second time does nothing
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: '{{ db_password1 }}'
|
||||
encrypted: '{{ encrypted }}'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- block: ¬_changed # block is only used here in order to be able to define YAML anchor
|
||||
- name: Check that ansible reports no change
|
||||
assert:
|
||||
that:
|
||||
- "{{ result is not changed }}"
|
||||
|
||||
- name: 'Define an expiration time'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
expires: '2025-01-01'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: 'Redefine the same expiration time'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
expires: '2025-01-01'
|
||||
<<: *parameters
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- block:
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password not changed when using cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: '{{ db_password1 }}'
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: "Using MD5-hashed password: check that password not changed when using md5 hash with 'ENCRYPTED'"
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: "Using MD5-hashed password: check that password not changed when using md5 hash with 'UNENCRYPTED'"
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Redefine the same expiration time and password (encrypted)'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
encrypted: 'yes'
|
||||
password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
|
||||
expires: '2025-01-01'
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password changed when using another cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: 'prefix{{ db_password1 }}'
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: "Using MD5-hashed password: check that password changed when using another md5 hash with 'ENCRYPTED'"
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "md5{{ ('prefix1' ~ db_password1 ~ db_user1) | hash('md5')}}"
|
||||
encrypted: 'yes'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: "Using MD5-hashed password: check that password changed when using md5 hash with 'UNENCRYPTED'"
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "md5{{ ('prefix2' ~ db_password1 ~ db_user1) | hash('md5')}}"
|
||||
encrypted: 'no'
|
||||
register: change_pass_unencrypted
|
||||
failed_when:
|
||||
- change_pass_unencrypted is failed
|
||||
# newer version of psycopg2 no longer supported unencrypted password, we ignore the error
|
||||
- '"UNENCRYPTED PASSWORD is no longer supported" not in change_pass_unencrypted.msg'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password changed when clearing the password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password not changed when clearing the password again'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using cleartext password: check that password not changed when clearing the password again'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password changed when using a cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: '{{ db_password1 }}'
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
when: encrypted == 'yes'
|
||||
|
||||
- block:
|
||||
|
||||
- name: 'Using cleartext password: check that password not changed when using cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "{{ db_password1 }}"
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Redefine the same expiration time and password (not encrypted)'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "{{ db_password1 }}"
|
||||
encrypted: 'no'
|
||||
expires: '2025-01-01'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using cleartext password: check that password changed when using another cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "changed{{ db_password1 }}"
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: 'Using cleartext password: check that password changed when clearing the password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: 'Using cleartext password: check that password not changed when clearing the password again'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using MD5-hashed password: check that password not changed when clearing the password again'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: ''
|
||||
encrypted: 'yes'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
- name: 'Using cleartext password: check that password changed when using cleartext password'
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
<<: *parameters
|
||||
password: "{{ db_password1 }}"
|
||||
encrypted: 'no'
|
||||
environment:
|
||||
PGCLIENTENCODING: 'UTF8'
|
||||
|
||||
- <<: *changed
|
||||
|
||||
when: encrypted == 'no'
|
||||
|
||||
- name: Remove user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
state: 'absent'
|
||||
<<: *parameters
|
||||
|
||||
- <<: *changed
|
||||
|
||||
- name: Check that they were removed
|
||||
<<: *task_parameters
|
||||
shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result.stdout_lines[-1] == '(0 rows)'"
|
||||
|
||||
- name: Check that removing user a second time does nothing
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
state: 'absent'
|
||||
<<: *parameters
|
||||
environment:
|
||||
PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed
|
||||
|
||||
- <<: *not_changed
|
||||
|
||||
always:
|
||||
- name: Remove user
|
||||
<<: *task_parameters
|
||||
postgresql_user:
|
||||
state: 'absent'
|
||||
<<: *parameters
|
3
test/integration/targets/incidental_selinux/aliases
Normal file
3
test/integration/targets/incidental_selinux/aliases
Normal file
|
@ -0,0 +1,3 @@
|
|||
needs/root
|
||||
shippable/posix/incidental
|
||||
skip/aix
|
36
test/integration/targets/incidental_selinux/tasks/main.yml
Normal file
36
test/integration/targets/incidental_selinux/tasks/main.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
# (c) 2017, Sam Doran <sdoran@redhat.com>
|
||||
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
- 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'
|
364
test/integration/targets/incidental_selinux/tasks/selinux.yml
Normal file
364
test/integration/targets/incidental_selinux/tasks/selinux.yml
Normal file
|
@ -0,0 +1,364 @@
|
|||
# (c) 2017, Sam Doran <sdoran@redhat.com>
|
||||
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# 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'
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
|
||||
- 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
|
2
test/integration/targets/incidental_setup_docker/aliases
Normal file
2
test/integration/targets/incidental_setup_docker/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
needs/target/setup_epel
|
||||
hidden
|
|
@ -0,0 +1,16 @@
|
|||
docker_cli_version: '0.0'
|
||||
docker_api_version: '0.0'
|
||||
docker_py_version: '0.0'
|
||||
docker_skip_cleanup: no
|
||||
docker_prereq_packages: []
|
||||
docker_packages:
|
||||
- docker-ce
|
||||
|
||||
docker_pip_extra_packages: []
|
||||
docker_pip_packages:
|
||||
- docker
|
||||
|
||||
docker_cleanup_packages:
|
||||
- docker
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
|
@ -0,0 +1,14 @@
|
|||
- name: remove pip packages
|
||||
pip:
|
||||
state: present
|
||||
name: "{{ docker_pip_packages | union(docker_pip_extra_packages) }}"
|
||||
listen: cleanup docker
|
||||
when: not docker_skip_cleanup | bool
|
||||
|
||||
- name: remove docker pagkages
|
||||
action: "{{ ansible_facts.pkg_mgr }}"
|
||||
args:
|
||||
name: "{{ docker_cleanup_packages }}"
|
||||
state: absent
|
||||
listen: cleanup docker
|
||||
when: not docker_skip_cleanup | bool
|
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- setup_remote_constraints
|
|
@ -0,0 +1,43 @@
|
|||
- name: Get OS version
|
||||
shell: uname -r
|
||||
register: os_version
|
||||
|
||||
- name: Install pre-reqs
|
||||
apt:
|
||||
name: "{{ docker_prereq_packages }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
notify: cleanup docker
|
||||
|
||||
- name: Add gpg key
|
||||
shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg >key && apt-key add key
|
||||
|
||||
- name: Add Docker repo
|
||||
shell: add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
|
||||
- block:
|
||||
- name: Prevent service restart
|
||||
copy:
|
||||
content: exit 101
|
||||
dest: /usr/sbin/policy-rc.d
|
||||
backup: yes
|
||||
mode: 0755
|
||||
register: policy_rc_d
|
||||
|
||||
- name: Install Docker CE
|
||||
apt:
|
||||
name: "{{ docker_packages }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
always:
|
||||
- name: Restore /usr/sbin/policy-rc.d (if needed)
|
||||
command: mv {{ policy_rc_d.backup_file }} /usr/sbin/policy-rc.d
|
||||
when:
|
||||
- "'backup_file' in policy_rc_d"
|
||||
|
||||
- name: Remove /usr/sbin/policy-rc.d (if needed)
|
||||
file:
|
||||
path: /usr/sbin/policy-rc.d
|
||||
state: absent
|
||||
when:
|
||||
- "'backup_file' not in policy_rc_d"
|
|
@ -0,0 +1,21 @@
|
|||
- name: Add repository
|
||||
yum_repository:
|
||||
file: docker-ce
|
||||
name: docker-ce-stable
|
||||
description: Docker CE Stable - $basearch
|
||||
baseurl: https://download.docker.com/linux/fedora/$releasever/$basearch/stable
|
||||
enabled: yes
|
||||
gpgcheck: yes
|
||||
gpgkey: https://download.docker.com/linux/fedora/gpg
|
||||
|
||||
- name: Update cache
|
||||
command: dnf makecache
|
||||
args:
|
||||
warn: no
|
||||
|
||||
- name: Install docker
|
||||
dnf:
|
||||
name: "{{ docker_packages }}"
|
||||
state: present
|
||||
enablerepo: docker-ce-test
|
||||
notify: cleanup docker
|
|
@ -0,0 +1,39 @@
|
|||
# The RHEL extras repository must be enabled to provide the container-selinux package.
|
||||
# See: https://docs.docker.com/engine/installation/linux/docker-ee/rhel/#install-using-the-repository
|
||||
|
||||
- name: Install Docker pre-reqs
|
||||
yum:
|
||||
name: "{{ docker_prereq_packages }}"
|
||||
state: present
|
||||
notify: cleanup docker
|
||||
|
||||
- name: Install epel repo which is missing on rhel-7 and is needed for pigz (needed for docker-ce 18)
|
||||
include_role:
|
||||
name: setup_epel
|
||||
|
||||
- name: Enable extras repository for RHEL on AWS
|
||||
command: yum-config-manager --enable rhui-REGION-rhel-server-extras
|
||||
args:
|
||||
warn: no
|
||||
|
||||
- name: Add repository
|
||||
command: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
args:
|
||||
warn: no
|
||||
|
||||
- name: Update cache
|
||||
command: yum -y makecache fast
|
||||
args:
|
||||
warn: no
|
||||
|
||||
- name: Install docker
|
||||
yum:
|
||||
name: "{{ docker_packages }}"
|
||||
state: present
|
||||
notify: cleanup docker
|
||||
|
||||
- name: Make sure the docker daemon is running (failure expected inside docker container)
|
||||
service:
|
||||
name: docker
|
||||
state: started
|
||||
ignore_errors: "{{ ansible_virtualization_type == 'docker' }}"
|
|
@ -0,0 +1,29 @@
|
|||
# The RHEL extras repository must be enabled to provide the container-selinux package.
|
||||
# See: https://docs.docker.com/engine/installation/linux/docker-ee/rhel/#install-using-the-repository
|
||||
|
||||
- name: Install Docker pre-reqs
|
||||
dnf:
|
||||
name: "{{ docker_prereq_packages }}"
|
||||
state: present
|
||||
notify: cleanup docker
|
||||
register: result
|
||||
until: result is success
|
||||
retries: 10
|
||||
delay: 2
|
||||
|
||||
- name: Set-up repository
|
||||
command: dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
args:
|
||||
warn: no
|
||||
|
||||
- name: Install docker
|
||||
dnf:
|
||||
name: "{{ docker_packages }}"
|
||||
state: present
|
||||
notify: cleanup docker
|
||||
|
||||
- name: Make sure the docker daemon is running (failure expected inside docker container)
|
||||
service:
|
||||
name: docker
|
||||
state: started
|
||||
ignore_errors: "{{ ansible_virtualization_type == 'docker' }}"
|
|
@ -0,0 +1,7 @@
|
|||
- name: Install docker 17
|
||||
zypper:
|
||||
name: "{{ docker_packages }}"
|
||||
force: yes
|
||||
disable_gpg_check: yes
|
||||
update_cache: yes
|
||||
notify: cleanup docker
|
113
test/integration/targets/incidental_setup_docker/tasks/main.yml
Normal file
113
test/integration/targets/incidental_setup_docker/tasks/main.yml
Normal file
|
@ -0,0 +1,113 @@
|
|||
- name: Setup Docker
|
||||
when: ansible_facts.distribution ~ ansible_facts.distribution_major_version not in ['CentOS6', 'RedHat6']
|
||||
block:
|
||||
- name: Include distribution specific variables
|
||||
include_vars: "{{ lookup('first_found', params) }}"
|
||||
vars:
|
||||
params:
|
||||
files:
|
||||
- "{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml"
|
||||
- "{{ ansible_facts.os_family }}-{{ ansible_facts.distribution_major_version }}.yml"
|
||||
- "{{ ansible_facts.distribution }}.yml"
|
||||
- "{{ ansible_facts.os_family }}.yml"
|
||||
- default.yml
|
||||
paths:
|
||||
- "{{ role_path }}/vars"
|
||||
|
||||
- name: Include distribution specific tasks
|
||||
include_tasks: "{{ lookup('first_found', params) }}"
|
||||
vars:
|
||||
params:
|
||||
files:
|
||||
- "{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml"
|
||||
- "{{ ansible_facts.os_family }}-{{ ansible_facts.distribution_major_version }}.yml"
|
||||
- "{{ ansible_facts.distribution }}.yml"
|
||||
- "{{ ansible_facts.os_family }}.yml"
|
||||
paths:
|
||||
- "{{ role_path }}/tasks"
|
||||
|
||||
- name: Install Python requirements
|
||||
pip:
|
||||
state: present
|
||||
name: "{{ docker_pip_packages | union(docker_pip_extra_packages) }}"
|
||||
extra_args: "-c {{ remote_constraints }}"
|
||||
notify: cleanup docker
|
||||
|
||||
# Detect docker CLI, API and docker-py versions
|
||||
- name: Check Docker CLI version
|
||||
command: "docker version -f {% raw %}'{{.Client.Version}}'{% endraw %}"
|
||||
register: docker_cli_version_stdout
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check Docker API version
|
||||
command: "{{ ansible_python.executable }} -c 'import docker; print(docker.from_env().version()[\"ApiVersion\"])'"
|
||||
register: docker_api_version_stdout
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check docker-py API version
|
||||
command: "{{ ansible_python.executable }} -c 'import docker; print(docker.__version__)'"
|
||||
register: docker_py_version_stdout
|
||||
ignore_errors: yes
|
||||
|
||||
- set_fact:
|
||||
docker_cli_version: "{{ docker_cli_version_stdout.stdout | default('0.0') }}"
|
||||
docker_api_version: "{{ docker_api_version_stdout.stdout | default('0.0') }}"
|
||||
docker_py_version: "{{ docker_py_version_stdout.stdout | default('0.0') }}"
|
||||
|
||||
- debug:
|
||||
msg: "Docker CLI version: {{ docker_cli_version }}; Docker API version: {{ docker_api_version }}; docker-py library version: {{ docker_py_version }}"
|
||||
|
||||
- block:
|
||||
# Cleanup docker daemon
|
||||
- name: "Remove all ansible-test-* docker containers"
|
||||
shell: 'docker ps --no-trunc --format {% raw %}"{{.Names}}"{% endraw %} | grep "^ansible-test-" | xargs -r docker rm -f'
|
||||
register: docker_containers
|
||||
retries: 3
|
||||
delay: 3
|
||||
until: docker_containers is success
|
||||
|
||||
- name: "Remove all ansible-test-* docker volumes"
|
||||
shell: 'docker volume ls --format {% raw %}"{{.Name}}"{% endraw %} | grep "^ansible-test-" | xargs -r docker volume rm -f'
|
||||
register: docker_volumes
|
||||
|
||||
- name: "Remove all ansible-test-* docker networks"
|
||||
shell: 'docker network ls --no-trunc --format {% raw %}"{{.Name}}"{% endraw %} | grep "^ansible-test-" | xargs -r docker network rm'
|
||||
register: docker_networks
|
||||
|
||||
- name: Cleaned docker resources
|
||||
debug:
|
||||
var: docker_resources
|
||||
vars:
|
||||
docker_resources:
|
||||
containers: "{{ docker_containers.stdout_lines }}"
|
||||
volumes: "{{ docker_volumes.stdout_lines }}"
|
||||
networks: "{{ docker_networks.stdout_lines }}"
|
||||
|
||||
# List all existing docker resources
|
||||
- name: List all docker containers
|
||||
command: docker ps --no-trunc -a
|
||||
register: docker_containers
|
||||
|
||||
- name: List all docker volumes
|
||||
command: docker volume ls
|
||||
register: docker_volumes
|
||||
|
||||
- name: List all docker networks
|
||||
command: docker network ls --no-trunc
|
||||
register: docker_networks
|
||||
|
||||
- name: List all docker images
|
||||
command: docker images --no-trunc -a
|
||||
register: docker_images
|
||||
|
||||
- name: Still existing docker resources
|
||||
debug:
|
||||
var: docker_resources
|
||||
vars:
|
||||
docker_resources:
|
||||
containers: "{{ docker_containers.stdout_lines }}"
|
||||
volumes: "{{ docker_volumes.stdout_lines }}"
|
||||
networks: "{{ docker_networks.stdout_lines }}"
|
||||
images: "{{ docker_images.stdout_lines }}"
|
||||
|
||||
when: docker_cli_version is version('0.0', '>')
|
|
@ -0,0 +1,5 @@
|
|||
docker_prereq_packages:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- software-properties-common
|
|
@ -0,0 +1,4 @@
|
|||
docker_prereq_packages: []
|
||||
|
||||
docker_packages:
|
||||
- docker-ce
|
|
@ -0,0 +1,8 @@
|
|||
docker_prereq_packages:
|
||||
- yum-utils
|
||||
- device-mapper-persistent-data
|
||||
- lvm2
|
||||
- libseccomp
|
||||
|
||||
docker_pip_extra_packages:
|
||||
- requests==2.6.0
|
|
@ -0,0 +1,9 @@
|
|||
docker_prereq_packages:
|
||||
- yum-utils
|
||||
- device-mapper-persistent-data
|
||||
- lvm2
|
||||
- libseccomp
|
||||
|
||||
# Docker CE > 3:18.09.1 requires containerd.io >= 1.2.2-3 which is unavaible at this time
|
||||
docker_packages:
|
||||
- docker-ce-3:18.09.1
|
|
@ -0,0 +1,2 @@
|
|||
docker_packages:
|
||||
- docker>=17
|
|
@ -0,0 +1,5 @@
|
|||
docker_pip_extra_packages:
|
||||
# Installing requests >=2.12.0 on Ubuntu 14.04 breaks certificate validation. We restrict to an older version
|
||||
# to ensure out get_url tests work out fine. This is only an issue if pyOpenSSL is also installed.
|
||||
# Not sure why RHEL7 needs this specific version
|
||||
- requests==2.6.0
|
|
@ -0,0 +1,138 @@
|
|||
# Create a dummy flatpak repository remote
|
||||
|
||||
This document describes how to create a local flatpak dummy repo. Just like the one contained in the `files/repo.tar.gxz` archive.
|
||||
|
||||
|
||||
## Create a hello world app
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- flathub
|
||||
|
||||
Prepare the environment:
|
||||
|
||||
```
|
||||
flatpak install --system flathub org.freedesktop.Platform//1.6 org.freedesktop.Sdk//1.6
|
||||
```
|
||||
|
||||
Create a hello world executable:
|
||||
|
||||
```
|
||||
echo $'#!/bin/sh\necho hello world' > hello.sh
|
||||
```
|
||||
|
||||
To create dummy flatpaks, run this (defining a unique NUM for every flatpak to add):
|
||||
|
||||
```
|
||||
export NUM=1
|
||||
flatpak build-init appdir$NUM com.dummy.App$NUM org.freedesktop.Sdk org.freedesktop.Platform 1.6;
|
||||
flatpak build appdir$NUM mkdir /app/bin;
|
||||
flatpak build appdir$NUM install --mode=750 hello.sh /app/bin;
|
||||
flatpak build-finish --command=hello.sh appdir$NUM
|
||||
```
|
||||
|
||||
## Create a repo and/or add the app to it
|
||||
|
||||
Create a repo and add the file to it in one command:
|
||||
|
||||
```
|
||||
flatpak build-export repo appdir$NUM stable
|
||||
```
|
||||
|
||||
## Create flatpak*-files
|
||||
|
||||
Put a flatpakref file under the repo folder (`repo/com.dummy.App1.flatpakref`):
|
||||
|
||||
```
|
||||
[Flatpak Ref]
|
||||
Title=Dummy App$NUM
|
||||
Name=com.dummy.App$NUM
|
||||
Branch=stable
|
||||
Url=file:///tmp/flatpak/repo
|
||||
GPGKey={{ base64-encoded public KEY }}
|
||||
IsRuntime=false
|
||||
RuntimeRepo=https://flathub.org/repo/flathub.flatpakrepo
|
||||
```
|
||||
|
||||
Add a `.flatpakrepo` file to the `repo` folder (`repo/dummy-repo.flatpakrepo`):
|
||||
|
||||
```
|
||||
[Flatpak Repo]
|
||||
Title=Dummy Repo
|
||||
Url=file:///tmp/flatpak/repo
|
||||
Comment=Dummy repo for ansible module integration testing
|
||||
Description=Dummy repo for ansible module integration testing
|
||||
GPGKey={{ base64-encoded public KEY }}
|
||||
```
|
||||
|
||||
## Sign the repo
|
||||
|
||||
Create a new key in a new gpg home folder (On RedHat systems, the executable needs to addressed as gpg2):
|
||||
|
||||
```
|
||||
mkdir gpg
|
||||
gpg --homedir gpg --quick-gen-key test@dummy.com
|
||||
```
|
||||
|
||||
Sign the repo and summary file, you need to redo this when you update the repository:
|
||||
|
||||
```
|
||||
flatpak build-sign repo --gpg-sign=KEY_ID --gpg-homedir=gpg
|
||||
flatpak build-update-repo repo --gpg-sign=KEY_ID --gpg-homedir=gpg
|
||||
```
|
||||
|
||||
Export the public key as a file:
|
||||
|
||||
```
|
||||
gpg --homedir=gpg --export KEY_ID > dummy-repo.gpg
|
||||
```
|
||||
|
||||
Create base64-encoded string from gpg-file for `GPGKey=` property in flatpak*-files:
|
||||
|
||||
```
|
||||
base64 dummy-repo.gpg | tr -d '\n'
|
||||
```
|
||||
|
||||
## How to use the repo
|
||||
|
||||
Now you can add the `repo` folder as a local repo:
|
||||
|
||||
```
|
||||
flatpak --system remote-add --gpg-import=/tmp/flatpak/repo/dummy-repo.gpg dummy-repo /tmp/flatpak/repo
|
||||
```
|
||||
|
||||
Or, via `.flatpakrepo` file:
|
||||
|
||||
```
|
||||
flatpak --system remote-add dummy-repo /tmp/flatpak/repo/dummy-repo.flatpakrepo
|
||||
```
|
||||
|
||||
And install the hello world flatpaks like this:
|
||||
|
||||
```
|
||||
flatpak --system install dummy-repo com.dummy.App$NUM
|
||||
```
|
||||
|
||||
Or from flatpakref:
|
||||
|
||||
```
|
||||
flatpak --system install --from /tmp/flatpak/repo/com.dummy.App$NUM.flatpakref
|
||||
```
|
||||
|
||||
Run the app:
|
||||
|
||||
```
|
||||
flatpak run com.dummy.App$NUM
|
||||
```
|
||||
|
||||
To install an app without any runtime dependencies (the app will be broken, but it is enough to test flatpak installation):
|
||||
|
||||
```
|
||||
flatpak --system install --no-deps dummy-repo com.dummy.App$NUM
|
||||
```
|
||||
|
||||
## Sources:
|
||||
|
||||
* https://blogs.gnome.org/alexl/2017/02/10/maintaining-a-flatpak-repository/
|
||||
|
||||
* http://docs.flatpak.org/en/latest/first-build.html
|
|
@ -0,0 +1 @@
|
|||
hidden
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
- name: remove temporary flatpak link
|
||||
file:
|
||||
state: absent
|
||||
path: /tmp/flatpak
|
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- setup_remote_tmp_dir
|
|
@ -0,0 +1,22 @@
|
|||
- name: Set up dummy flatpak repository remote
|
||||
block:
|
||||
|
||||
- name: Copy repo into place
|
||||
unarchive:
|
||||
src: repo.tar.xz
|
||||
dest: "{{ remote_tmp_dir }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Create deterministic link to temp directory
|
||||
file:
|
||||
state: link
|
||||
src: "{{ remote_tmp_dir }}/"
|
||||
path: "/tmp/flatpak"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
notify: remove temporary flatpak link
|
||||
|
||||
become: true
|
|
@ -0,0 +1 @@
|
|||
hidden
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue