Initial commit

This commit is contained in:
Ansible Core Team
2020-03-09 13:15:28 +00:00
commit 6f928621f0
245 changed files with 17544 additions and 0 deletions

1
tests/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
output/

View File

@@ -0,0 +1,2 @@
shippable/posix/group2
skip/aix

View File

@@ -0,0 +1,205 @@
# (c) 2017, Martin Krizek <mkrizek@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/>.
- name: Create ansible user
user:
name: "{{ test_user }}"
- name: Create ansible group
group:
name: "{{ test_group }}"
- name: Create ansible file
file:
path: "{{ test_file }}"
state: touch
- name: Create ansible dir
file:
path: "{{ test_dir }}"
state: directory
##############################################################################
- name: Grant ansible user read access to a file
acl:
path: "{{ test_file }}"
entity: "{{ test_user }}"
etype: user
permissions: r
state: present
register: output
- name: get getfacl output
shell: "getfacl {{ test_file | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is changed
- output is not failed
- "'user:{{ test_user }}:r--' in output.acl"
- "'user:{{ test_user }}:r--' in getfacl_output.stdout_lines"
##############################################################################
- name: Obtain the acl for a specific file
acl:
path: "{{ test_file }}"
register: output
- name: get getfacl output
shell: "getfacl {{ test_file | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is not changed
- output is not failed
- "'user::rw-' in output.acl"
- "'user:{{ test_user }}:r--' in output.acl"
- "'group::r--' in output.acl"
- "'mask::r--' in output.acl"
- "'other::r--' in output.acl"
- "'user::rw-' in getfacl_output.stdout_lines"
- "'user:{{ test_user }}:r--' in getfacl_output.stdout_lines"
- "'group::r--' in getfacl_output.stdout_lines"
- "'mask::r--' in getfacl_output.stdout_lines"
- "'other::r--' in getfacl_output.stdout_lines"
##############################################################################
- name: Removes the acl for ansible user on a specific file
acl:
path: "{{ test_file }}"
entity: "{{ test_user }}"
etype: user
state: absent
register: output
- name: get getfacl output
shell: "getfacl {{ test_file | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is changed
- output is not failed
- "'user:{{ test_user }}:r--' not in output.acl"
- "'user:{{ test_user }}:r--' not in getfacl_output.stdout_lines"
##############################################################################
- name: Sets default acl for ansible user on ansible dir
acl:
path: "{{ test_dir }}"
entity: "{{ test_user }}"
etype: user
permissions: rw
default: yes
state: present
register: output
- name: get getfacl output
shell: "getfacl {{ test_dir | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is changed
- output is not failed
- "'user:{{ test_user }}:rw-' in output.acl"
- "'default:user:{{ test_user }}:rw-' in getfacl_output.stdout_lines"
##############################################################################
- name: Cleanup
shell: "setfacl -b {{ test_dir | quote }}"
##############################################################################
- name: Same as previous but using entry shorthand
acl:
path: "{{ test_dir }}"
entry: "user:{{ test_user }}:rw-"
default: yes
state: present
register: output
- name: get getfacl output
shell: "getfacl {{ test_dir | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is changed
- output is not failed
- "'user:{{ test_user }}:rw-' in output.acl"
- "'default:user:{{ test_user }}:rw-' in getfacl_output.stdout_lines"
##############################################################################
- name: Same as previous, to test idempotence
acl:
path: "{{ test_dir }}"
entry: "user:{{ test_user }}:rw-"
default: yes
state: present
register: output
- name: get getfacl output
shell: "getfacl {{ test_dir | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is not changed
- output is not failed
- "'user:{{ test_user }}:rw-' in output.acl"
- "'default:user:{{ test_user }}:rw-' in getfacl_output.stdout_lines"
##############################################################################
- name: Cleanup
shell: "setfacl -b {{ test_dir | quote }}"
##############################################################################
- name: Set default acls
acl:
path: "{{ test_dir }}"
entry: "{{ item }}"
default: yes
state: present
with_items:
- "user:{{ test_user }}:rw-"
- "group:{{ test_group }}:rw-"
- name: Remove default group test_user acl
acl:
path: "{{ test_dir }}"
entry: "group:{{ test_group }}:rw-"
default: yes
state: absent
register: output
- name: get getfacl output
shell: "getfacl {{ test_dir | quote }}"
register: getfacl_output
- name: verify output
assert:
that:
- output is changed
- output is not failed
- "'user::rwx' in getfacl_output.stdout_lines"
- "'group::r-x' in getfacl_output.stdout_lines"
- "'other::r-x' in getfacl_output.stdout_lines"
- "'default:user::rwx' in getfacl_output.stdout_lines"
- "'default:user:{{ test_user }}:rw-' in getfacl_output.stdout_lines"
- "'default:group::r-x' in getfacl_output.stdout_lines"
- "'default:mask::rwx' in getfacl_output.stdout_lines"
- "'default:other::r-x' in getfacl_output.stdout_lines"
- "'default:group:{{ test_group }}:rw-' not in getfacl_output.stdout_lines"

View File

@@ -0,0 +1,36 @@
# (c) 2017, Martin Krizek <mkrizek@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/>.
- block:
- include: acl.yml
when: ansible_system == 'Linux' # TODO enable acls mount option on FreeBSD to test it there too
always:
- name: delete created directory and file
file:
path: '{{ item }}'
state: absent
with_items:
- '{{ test_dir }}'
- '{{ test_file }}'
vars:
test_user: ansible_user
test_group: ansible_group
test_file: '{{ output_dir }}/ansible file'
test_dir: "{{ output_dir }}/ansible_dir/with some space"

View File

@@ -0,0 +1,2 @@
shippable/posix/group1
destructive

View File

@@ -0,0 +1,2 @@
dependencies:
- prepare_tests

View File

@@ -0,0 +1,62 @@
# Test code for the at module.
# (c) 2017, James Tanner <tanner.jc@gmail.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/>.
- set_fact: output_dir_test={{output_dir}}/at
- name: make sure our testing sub-directory does not exist
file: path="{{ output_dir_test }}" state=absent
- name: create our testing sub-directory
file: path="{{ output_dir_test }}" state=directory
##
## at
##
- name: define distros to attempt installing at on
set_fact:
package_distros:
- RedHat
- CentOS
- ScientificLinux
- Fedora
- Ubuntu
- Debian
- openSUSE Leap
- name: ensure at is installed
package:
name: at
state: present
when: ansible_distribution in package_distros
- name: run the first example
at:
command: "ls -d / > /dev/null"
count: 20
units: minutes
register: at_test0
- debug: var=at_test0
- name: validate results
assert:
that:
- 'at_test0.changed is defined'
- 'at_test0.count is defined'
- 'at_test0.script_file is defined'
- 'at_test0.state is defined'
- 'at_test0.units is defined'

View File

@@ -0,0 +1,2 @@
needs/root
shippable/posix/group2

View File

@@ -0,0 +1,36 @@
dss_key_basic: ssh-dss DATA_BASIC root@testing
dss_key_unquoted_option: idle-timeout=5m ssh-dss DATA_UNQUOTED_OPTION root@testing
dss_key_command: command="/bin/true" ssh-dss DATA_COMMAND root@testing
dss_key_complex_command: command="echo foo 'bar baz'" ssh-dss DATA_COMPLEX_COMMAND root@testing
dss_key_command_single_option: no-port-forwarding,command="/bin/true" ssh-dss DATA_COMMAND_SINGLE_OPTIONS root@testing
dss_key_command_multiple_options: no-port-forwarding,idle-timeout=5m,command="/bin/true" ssh-dss DATA_COMMAND_MULTIPLE_OPTIONS root@testing
dss_key_trailing: ssh-dss DATA_TRAILING root@testing foo bar baz
rsa_key_basic: ssh-rsa DATA_BASIC root@testing
multiple_key_base: |
ssh-rsa DATA_BASIC 1@testing
ssh-dss DATA_TRAILING 2@testing foo bar baz
ssh-dss DATA_TRAILING 3@testing foo bar baz
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
multiple_key_different_order: |
ssh-dss DATA_TRAILING 2@testing foo bar baz
ssh-dss DATA_TRAILING 3@testing foo bar baz
ssh-rsa DATA_BASIC 1@testing
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
multiple_key_different_order_2: |
ssh-dss DATA_TRAILING 2@testing foo bar baz
ssh-rsa WHATEVER 2.5@testing
ssh-dss DATA_TRAILING 3@testing foo bar baz
ssh-rsa DATA_BASIC 1@testing
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
multiple_key_exclusive: |
ssh-rsa DATA_BASIC 1@testing
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
multiple_keys_comments: |
ssh-rsa DATA_BASIC 1@testing
# I like adding comments yo-dude-this-is-not-a-key INVALID_DATA 2@testing
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing

View File

@@ -0,0 +1,5 @@
# I like candy
ssh-rsa somekeydata somekeyalias
# It is a very pleasant temperature outside today.
ssh-rsa otherkeydata otherkeyalias

View File

@@ -0,0 +1,2 @@
dependencies:
- prepare_tests

View File

@@ -0,0 +1,485 @@
# test code for the authorized_key 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/>.
# -------------------------------------------------------------
# Setup steps
- name: copy an existing file in place with comments
copy:
src: existing_authorized_keys
dest: "{{ output_dir | expanduser }}/authorized_keys"
- name: add multiple keys different order
authorized_key:
user: root
key: "{{ multiple_key_different_order_2 }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: get the file content
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
changed_when: no
register: multiple_keys_existing
- name: assert that the key was added and comments and ordering preserved
assert:
that:
- 'result.changed == True'
- '"# I like candy" in multiple_keys_existing.stdout'
- '"# I like candy" in multiple_keys_existing.stdout_lines[0]'
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout'
# The specific index is a little fragile, but I want to verify the line shows up
# as the 3rd line in the new entries after the existing entries and comments are preserved
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout_lines[7]'
# start afresh
- name: remove file foo.txt
file:
path: "{{ output_dir | expanduser }}/authorized_keys"
state: absent
- name: touch the authorized_keys file
file:
dest: "{{ output_dir }}/authorized_keys"
state: touch
register: result
- name: assert that the authorized_keys file was created
assert:
that:
- 'result.changed == True'
- 'result.state == "file"'
- name: add multiple keys
authorized_key:
user: root
key: "{{ multiple_key_base }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == multiple_key_base'
- 'result.key_options == None'
- name: add multiple keys different order
authorized_key:
user: root
key: "{{ multiple_key_different_order }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == multiple_key_different_order'
- 'result.key_options == None'
- name: add multiple keys exclusive
authorized_key:
user: root
key: "{{ multiple_key_exclusive }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
exclusive: true
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == multiple_key_exclusive'
- 'result.key_options == None'
- name: add multiple keys in different calls
authorized_key:
user: root
key: "ecdsa-sha2-nistp521 ECDSA_DATA 4@testing"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: add multiple keys in different calls
authorized_key:
user: root
key: "ssh-rsa DATA_BASIC 1@testing"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: get the file content
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
changed_when: no
register: multiple_keys_at_a_time
- name: assert that the key was added
assert:
that:
- 'result.changed == false'
- 'multiple_keys_at_a_time.stdout == multiple_key_exclusive.strip()'
- name: add multiple keys comment
authorized_key:
user: root
key: "{{ multiple_keys_comments }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
exclusive: true
register: result
- name: get the file content
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
changed_when: no
register: multiple_keys_comments
- name: assert that the keys exist and comment only lines were not added
assert:
that:
- 'result.changed == False'
- 'multiple_keys_comments.stdout == multiple_key_exclusive.strip()'
- 'result.key_options == None'
# -------------------------------------------------------------
# basic ssh-dss key
- name: add basic ssh-dss key
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_basic'
- 'result.key_options == None'
- name: re-add basic ssh-dss key
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with an unquoted option
- name: add ssh-dss key with an unquoted option
authorized_key:
user: root
key: "{{ dss_key_unquoted_option }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_unquoted_option'
- 'result.key_options == None'
- name: re-add ssh-dss key with an unquoted option
authorized_key:
user: root
key: "{{ dss_key_unquoted_option }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with a leading command="/bin/foo"
- name: add ssh-dss key with a leading command
authorized_key:
user: root
key: "{{ dss_key_command }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_command'
- 'result.key_options == None'
- name: re-add ssh-dss key with a leading command
authorized_key:
user: root
key: "{{ dss_key_command }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with a complex quoted leading command
# ie. command="/bin/echo foo 'bar baz'"
- name: add ssh-dss key with a complex quoted leading command
authorized_key:
user: root
key: "{{ dss_key_complex_command }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_complex_command'
- 'result.key_options == None'
- name: re-add ssh-dss key with a complex quoted leading command
authorized_key:
user: root
key: "{{ dss_key_complex_command }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with a command and a single option, which are
# in a comma-separated list
- name: add ssh-dss key with a command and a single option
authorized_key:
user: root
key: "{{ dss_key_command_single_option }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_command_single_option'
- 'result.key_options == None'
- name: re-add ssh-dss key with a command and a single option
authorized_key:
user: root
key: "{{ dss_key_command_single_option }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with a command and multiple other options
- name: add ssh-dss key with a command and multiple options
authorized_key:
user: root
key: "{{ dss_key_command_multiple_options }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_command_multiple_options'
- 'result.key_options == None'
- name: re-add ssh-dss key with a command and multiple options
authorized_key:
user: root
key: "{{ dss_key_command_multiple_options }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# ssh-dss key with multiple trailing parts, which are space-
# separated and not quoted in any way
- name: add ssh-dss key with trailing parts
authorized_key:
user: root
key: "{{ dss_key_trailing }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_trailing'
- 'result.key_options == None'
- name: re-add ssh-dss key with trailing parts
authorized_key:
user: root
key: "{{ dss_key_trailing }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that nothing changed
assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# basic ssh-dss key with mutliple permit-open options
# https://github.com/ansible/ansible-modules-core/issues/1715
- name: add basic ssh-dss key with multi-opts
authorized_key:
user: root
key: "{{ dss_key_basic }}"
key_options: 'no-agent-forwarding,no-X11-forwarding,permitopen="10.9.8.1:8080",permitopen="10.9.8.1:9001"'
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: assert that the key with multi-opts was added
assert:
that:
- 'result.changed == True'
- 'result.key == dss_key_basic'
- 'result.key_options == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\""'
- name: get the file content
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
changed_when: no
register: content
- name: validate content
assert:
that:
- 'content.stdout == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\" ssh-dss DATA_BASIC root@testing"'
# -------------------------------------------------------------
# check mode
- name: copy an existing file in place with comments
copy:
src: existing_authorized_keys
dest: "{{ output_dir | expanduser }}/authorized_keys"
- authorized_key:
user: root
key: "{{ multiple_key_different_order_2 }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
check_mode: True
register: result
- name: assert that the file was not changed
copy:
src: existing_authorized_keys
dest: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- assert:
that:
- 'result.changed == False'
# -------------------------------------------------------------
# comments
- name: Add rsa key with existing comment
authorized_key:
user: root
key: "{{ rsa_key_basic }}"
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: Change the comment on an existing key
authorized_key:
user: root
key: "{{ rsa_key_basic }}"
comment: user@acme.com
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: get the file content
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
changed_when: no
register: content
- name: Assert that comment on an existing key was changed
assert:
that:
- "'user@acme.com' in content.stdout"
- name: Set the same key with comment to ensure no changes are reported
authorized_key:
user: root
key: "{{ rsa_key_basic }}"
comment: user@acme.com
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: Assert that no changes were made when running again
assert:
that:
- not result.changed
- debug:
var: "{{ item }}"
verbosity: 1
with_items:
- result
- content

View File

@@ -0,0 +1,4 @@
needs/privileged
needs/root
shippable/posix/group2
skip/aix

View File

@@ -0,0 +1,280 @@
- name: Create the mount point
file:
state: directory
path: '{{ output_dir }}/mount_dest'
- name: Create a directory to bind mount
file:
state: directory
path: '{{ output_dir }}/mount_source'
- name: Put something in the directory so we see that it worked
copy:
content: 'Testing
'
dest: '{{ output_dir }}/mount_source/test_file'
register: orig_info
- name: Bind mount a filesystem (Linux)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: None
opts: bind
when: ansible_system == 'Linux'
register: bind_result_linux
- name: Bind mount a filesystem (FreeBSD)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: nullfs
when: ansible_system == 'FreeBSD'
register: bind_result_freebsd
- name: get checksum for bind mounted file
stat:
path: '{{ output_dir }}/mount_dest/test_file'
when: ansible_system in ('FreeBSD', 'Linux')
register: dest_stat
- name: assert the bind mount was successful
assert:
that:
- (ansible_system == 'Linux' and bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and bind_result_freebsd['changed'])
- dest_stat['stat']['exists']
- orig_info['checksum'] == dest_stat['stat']['checksum']
when: ansible_system in ('FreeBSD', 'Linux')
- name: Bind mount a filesystem (Linux)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: None
opts: bind
when: ansible_system == 'Linux'
register: bind_result_linux
- name: Bind mount a filesystem (FreeBSD)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: nullfs
when: ansible_system == 'FreeBSD'
register: bind_result_freebsd
- name: Make sure we didn't mount a second time
assert:
that:
- (ansible_system == 'Linux' and not bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and not bind_result_freebsd['changed'])
when: ansible_system in ('FreeBSD', 'Linux')
- name: Remount filesystem with different opts (Linux)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: None
opts: bind,ro
when: ansible_system == 'Linux'
register: bind_result_linux
- name: Remount filesystem with different opts (FreeBSD)
mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: nullfs
opts: ro
when: ansible_system == 'FreeBSD'
register: bind_result_freebsd
- name: Get mount options
shell: mount | grep mount_dest | grep -E -w '(ro|read-only)' | wc -l
register: remount_options
- name: Make sure the filesystem now has the new opts
assert:
that:
- (ansible_system == 'Linux' and bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and bind_result_freebsd['changed'])
- '''1'' in remount_options.stdout'
- 1 == remount_options.stdout_lines | length
when: ansible_system in ('FreeBSD', 'Linux')
- name: Unmount the bind mount
mount:
name: '{{ output_dir }}/mount_dest'
state: absent
when: ansible_system in ('Linux', 'FreeBSD')
register: unmount_result
- name: Make sure the file no longer exists in dest
stat:
path: '{{ output_dir }}/mount_dest/test_file'
when: ansible_system in ('FreeBSD', 'Linux')
register: dest_stat
- name: Check that we unmounted
assert:
that:
- unmount_result['changed']
- not dest_stat['stat']['exists']
when: ansible_system in ('FreeBSD', 'Linux')
- name: Create fstab record for the first swap file
mount:
name: none
src: /tmp/swap1
opts: sw
fstype: swap
state: present
register: swap1_created
when: ansible_system in ('Linux')
- name: Try to create fstab record for the first swap file again
mount:
name: none
src: /tmp/swap1
opts: sw
fstype: swap
state: present
register: swap1_created_again
when: ansible_system in ('Linux')
- name: Check that we created the swap1 record
assert:
that:
- swap1_created['changed']
- not swap1_created_again['changed']
when: ansible_system in ('Linux')
- name: Create fstab record for the second swap file
mount:
name: none
src: /tmp/swap2
opts: sw
fstype: swap
state: present
register: swap2_created
when: ansible_system in ('Linux')
- name: Try to create fstab record for the second swap file again
mount:
name: none
src: /tmp/swap1
opts: sw
fstype: swap
state: present
register: swap2_created_again
when: ansible_system in ('Linux')
- name: Check that we created the swap2 record
assert:
that:
- swap2_created['changed']
- not swap2_created_again['changed']
when: ansible_system in ('Linux')
- name: Remove the fstab record for the first swap file
mount:
name: none
src: /tmp/swap1
state: absent
register: swap1_removed
when: ansible_system in ('Linux')
- name: Try to remove the fstab record for the first swap file again
mount:
name: none
src: /tmp/swap1
state: absent
register: swap1_removed_again
when: ansible_system in ('Linux')
- name: Check that we removed the swap1 record
assert:
that:
- swap1_removed['changed']
- not swap1_removed_again['changed']
when: ansible_system in ('Linux')
- name: Remove the fstab record for the second swap file
mount:
name: none
src: /tmp/swap2
state: absent
register: swap2_removed
when: ansible_system in ('Linux')
- name: Try to remove the fstab record for the second swap file again
mount:
name: none
src: /tmp/swap2
state: absent
register: swap2_removed_again
when: ansible_system in ('Linux')
- name: Check that we removed the swap2 record
assert:
that:
- swap2_removed['changed']
- not swap2_removed_again['changed']
when: ansible_system in ('Linux')
- name: Create fstab record with missing last two fields
copy:
dest: /etc/fstab
content: '//nas/photo /home/jik/pictures cifs defaults,credentials=/etc/security/nas.creds,uid=jik,gid=users,forceuid,forcegid,noserverino,_netdev
'
when: ansible_system in ('Linux')
- name: Try to change the fstab record with the missing last two fields
mount:
src: //nas/photo
path: /home/jik/pictures
fstype: cifs
opts: defaults,credentials=/etc/security/nas.creds,uid=jik,gid=users,forceuid,forcegid,noserverino,_netdev,x-systemd.mount-timeout=0
state: present
register: optional_fields_update
when: ansible_system in ('Linux')
- name: Get the content of the fstab file
shell: cat /etc/fstab
register: optional_fields_content
when: ansible_system in ('Linux')
- name: Check if the line containing the missing last two fields was changed
assert:
that:
- optional_fields_update['changed']
- ''' 0 0'' in optional_fields_content.stdout'
- 1 == optional_fields_content.stdout_lines | length
when: ansible_system in ('Linux')
- name: Block to test remounted option
block:
- name: Create empty file
command: dd if=/dev/zero of=/tmp/myfs.img bs=1048576 count=20
when: ansible_system in ('Linux')
- name: Format FS
when: ansible_system in ('Linux')
community.general.filesystem:
fstype: ext3
dev: /tmp/myfs.img
- name: Mount the FS for the first time
mount:
path: /tmp/myfs
src: /tmp/myfs.img
fstype: ext2
state: mounted
when: ansible_system in ('Linux')
- name: Get the last write time
shell: 'dumpe2fs /tmp/myfs.img 2>/dev/null | grep -i last write time: |cut -d: -f2-'
register: last_write_time
when: ansible_system in ('Linux')
- name: Wait 2 second
pause:
seconds: 2
when: ansible_system in ('Linux')
- name: Test if the FS is remounted
mount:
path: /tmp/myfs
state: remounted
when: ansible_system in ('Linux')
- name: Get again the last write time
shell: 'dumpe2fs /tmp/myfs.img 2>/dev/null | grep -i last write time: |cut -d: -f2-'
register: last_write_time2
when: ansible_system in ('Linux')
- name: Fail if they are the same
fail:
msg: Filesytem was not remounted, testing of the module failed!
when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout and ansible_system in ('Linux')
always:
- name: Umount the test FS
mount:
path: /tmp/myfs
src: /tmp/myfs.img
opts: loop
state: absent
when: ansible_system in ('Linux')
- name: Remove the test FS
file:
path: '{{ item }}'
state: absent
loop:
- /tmp/myfs.img
- /tmp/myfs
when: ansible_system in ('Linux')

View File

@@ -0,0 +1,3 @@
destructive
shippable/posix/group2
skip/aix

View File

@@ -0,0 +1,19 @@
Stet clita kasd gubergren,no sea takimata sanctus est Lorem ipsum dolor
sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren,no sea takimata sanctus est Lorem ipsum dolor
sit amet.

View File

@@ -0,0 +1,24 @@
--- origin.txt 2018-05-12 10:22:14.155109584 +0200
+++ result.txt 2018-05-12 10:18:07.230811204 +0200
@@ -2,18 +2,12 @@
sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
-tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
-vero eos et accusam et justo duo dolores et ea rebum.
-
-Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
-sit amet.
-
-Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
-tempor invidunt ut labore et dolore magna aliquyam erat.
+tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
+At vero eos et accusam et justo duo dolores et ea rebum.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum.
-Stet clita kasd gubergren,no sea takimata sanctus est Lorem ipsum dolor
+Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.

View File

@@ -0,0 +1,13 @@
Stet clita kasd gubergren,no sea takimata sanctus est Lorem ipsum dolor
sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.

View File

@@ -0,0 +1,3 @@
---
dependencies:
- prepare_tests

View File

@@ -0,0 +1,89 @@
- name: ensure idempotency installed
package:
name: patch
when: ansible_distribution != "MacOSX"
- name: create a directory for the result
file:
dest: '{{ output_dir }}/patch'
state: directory
register: result
- name: assert the directory was created
assert:
that:
- result.state == 'directory'
- name: copy the origin file
copy:
src: ./origin.txt
dest: '{{ output_dir }}/patch/workfile.txt'
register: result
- name: patch the origin file in check mode
check_mode: true
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
- name: verify patch the origin file in check mode
assert:
that:
- result is changed
- name: patch the origin file
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
- name: verify patch the origin file
assert:
that:
- result is changed
- name: test patch the origin file idempotency
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
- name: verify test patch the origin file idempotency
assert:
that:
- result is not changed
- name: verify the resulted file matches expectations
copy:
src: ./result.txt
dest: '{{ output_dir }}/patch/workfile.txt'
register: result
failed_when: result is changed
- name: patch the workfile file in check mode state absent
check_mode: true
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
state: absent
- name: verify patch the workfile file in check mode state absent
assert:
that:
- result is changed
- name: patch the workfile file state absent
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
state: absent
- name: verify patch the workfile file state absent
assert:
that:
- result is changed
- name: patch the workfile file state absent idempotency
register: result
community.general.patch:
src: result.patch
dest: '{{ output_dir }}/patch/workfile.txt'
state: absent
- name: verify patch the workfile file state absent idempotency
assert:
that:
- result is not changed
- name: verify the resulted file matches expectations
copy:
src: ./origin.txt
dest: '{{ output_dir }}/patch/workfile.txt'
register: result
failed_when: result is changed

View File

@@ -0,0 +1,3 @@
needs/root
shippable/posix/group2
skip/aix

View File

@@ -0,0 +1,22 @@
# (c) 2017, Martin Krizek <mkrizek@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/>.
- include: seboolean.yml
when:
- ansible_selinux is defined
- ansible_selinux != False
- ansible_selinux.status == 'enabled'

View File

@@ -0,0 +1,86 @@
# (c) 2017, Martin Krizek <mkrizek@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/>.
- name: install requirements for RHEL 7 and earlier
package:
name: policycoreutils-python
when:
- ansible_distribution == 'RedHat' and ansible_distribution_major_version is version('7', '<=')
- name: install requirements for RHEL 8 and later
package:
name: policycoreutils-python-utils
when:
- ansible_distribution == 'RedHat' and ansible_distribution_major_version is version('8', '>=')
- name: Cleanup
shell: setsebool -P httpd_can_network_connect 0
##########################################################################################
- name: set flag and don't keep it persistent
seboolean:
name: httpd_can_network_connect
state: yes
register: output
- name: get getsebool output
shell: semanage boolean -l | grep 'httpd_can_network_connect\W'
register: getsebool_output
- name: check output
assert:
that:
- output is changed
- output is not failed
- output.name == 'httpd_can_network_connect'
- getsebool_output.stdout.startswith('httpd_can_network_connect (on , off)')
##########################################################################################
- name: unset flag
seboolean:
name: httpd_can_network_connect
state: no
- name: get getsebool output
shell: semanage boolean -l | grep 'httpd_can_network_connect\W'
register: getsebool_output
- name: check output
assert:
that:
- output is changed
- output is not failed
- output.name == 'httpd_can_network_connect'
- getsebool_output.stdout.startswith('httpd_can_network_connect (off , off)')
##########################################################################################
- name: set flag and keep it persistent
seboolean:
name: httpd_can_network_connect
state: yes
persistent: yes
register: output
- name: get getsebool output
shell: semanage boolean -l | grep 'httpd_can_network_connect\W'
register: getsebool_output
- name: check output
assert:
that:
- output is changed
- output is not failed
- output.name == 'httpd_can_network_connect'
- getsebool_output.stdout.startswith('httpd_can_network_connect (on , on)')
##########################################################################################

View File

@@ -0,0 +1,3 @@
needs/root
shippable/posix/group2
skip/aix

View 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'

View 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'

View File

@@ -0,0 +1,70 @@
- name: create user for testing
user:
name: seuser
- name: attempt to add mapping without 'seuser'
register: selogin_error
ignore_errors: true
community.general.selogin:
login: seuser
- name: verify failure
assert:
that:
- selogin_error is failed
- name: map login to SELinux user
register: selogin_new_mapping
check_mode: '{{ item }}'
with_items:
- true
- false
- true
- false
community.general.selogin:
login: seuser
seuser: staff_u
- 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
register: selogin_mod_mapping
check_mode: '{{ item }}'
with_items:
- true
- false
- true
- false
community.general.selogin:
login: seuser
seuser: user_u
- 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
register: selogin_del_mapping
check_mode: '{{ item }}'
with_items:
- true
- false
- true
- false
community.general.selogin:
login: seuser
state: absent
- 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

View File

@@ -0,0 +1 @@
shippable/posix/group2

View File

@@ -0,0 +1 @@
templated_var_loaded

View File

@@ -0,0 +1 @@
templated_var_loaded

View File

@@ -0,0 +1,2 @@
dependencies:
- prepare_tests

View File

@@ -0,0 +1,229 @@
- name: install rsync
package:
name: rsync
when: ansible_distribution != "MacOSX"
- name: cleanup old files
shell: rm -rf {{output_dir}}/*
- name: create test new files
copy: dest={{output_dir}}/{{item}} mode=0644 content="hello world"
with_items:
- foo.txt
- bar.txt
- name: synchronize file to new filename
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.result
register: sync_result
- assert:
that:
- '''changed'' in sync_result'
- sync_result.changed == true
- '''cmd'' in sync_result'
- '''rsync'' in sync_result.cmd'
- '''msg'' in sync_result'
- sync_result.msg.startswith('>f+')
- 'sync_result.msg.endswith(''+ foo.txt
'')'
- name: test that the file was really copied over
stat:
path: '{{ output_dir }}/foo.result'
register: stat_result
- assert:
that:
- stat_result.stat.exists == True
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
- name: test that the file is not copied a second time
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.result
register: sync_result
- assert:
that:
- sync_result.changed == False
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}'
with_items:
- foo.result
- bar.result
- name: Synchronize using the mode=push param
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/foo.result'
mode: push
register: sync_result
- assert:
that:
- '''changed'' in sync_result'
- sync_result.changed == true
- '''cmd'' in sync_result'
- '''rsync'' in sync_result.cmd'
- '''msg'' in sync_result'
- sync_result.msg.startswith('>f+')
- 'sync_result.msg.endswith(''+ foo.txt
'')'
- name: test that the file was really copied over
stat:
path: '{{ output_dir }}/foo.result'
register: stat_result
- assert:
that:
- stat_result.stat.exists == True
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
- name: test that the file is not copied a second time
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/foo.result'
mode: push
register: sync_result
- assert:
that:
- sync_result.changed == False
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}'
with_items:
- foo.result
- bar.result
- name: Synchronize using the mode=pull param
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/foo.result'
mode: pull
register: sync_result
- assert:
that:
- '''changed'' in sync_result'
- sync_result.changed == true
- '''cmd'' in sync_result'
- '''rsync'' in sync_result.cmd'
- '''msg'' in sync_result'
- sync_result.msg.startswith('>f+')
- 'sync_result.msg.endswith(''+ foo.txt
'')'
- name: test that the file was really copied over
stat:
path: '{{ output_dir }}/foo.result'
register: stat_result
- assert:
that:
- stat_result.stat.exists == True
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
- name: test that the file is not copied a second time
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/foo.result'
mode: pull
register: sync_result
- assert:
that:
- sync_result.changed == False
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}'
with_items:
- foo.result
- bar.result
- name: synchronize files using with_items (issue#5965)
synchronize: src={{output_dir}}/{{item}} dest={{output_dir}}/{{item}}.result
with_items:
- foo.txt
- bar.txt
register: sync_result
- assert:
that:
- sync_result.changed
- sync_result.msg == 'All items completed'
- '''results'' in sync_result'
- sync_result.results|length == 2
- 'sync_result.results[0].msg.endswith(''+ foo.txt
'')'
- 'sync_result.results[1].msg.endswith(''+ bar.txt
'')'
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}.result'
with_items:
- foo.txt
- bar.txt
- name: synchronize files using rsync_path (issue#7182)
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.rsync_path rsync_path="sudo rsync"
register: sync_result
- assert:
that:
- '''changed'' in sync_result'
- sync_result.changed == true
- '''cmd'' in sync_result'
- '''rsync'' in sync_result.cmd'
- '''rsync_path'' in sync_result.cmd'
- '''msg'' in sync_result'
- sync_result.msg.startswith('>f+')
- 'sync_result.msg.endswith(''+ foo.txt
'')'
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}'
with_items:
- foo.rsync_path
- name: add subdirectories for link-dest test
file:
path: '{{output_dir}}/{{item}}/'
state: directory
mode: '0755'
with_items:
- directory_a
- directory_b
- name: copy foo.txt into the first directory
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/{{item}}/foo.txt'
with_items:
- directory_a
- name: synchronize files using link_dest
synchronize:
src: '{{output_dir}}/directory_a/foo.txt'
dest: '{{output_dir}}/directory_b/foo.txt'
link_dest:
- '{{output_dir}}/directory_a'
register: sync_result
- name: get stat information for directory_a
stat:
path: '{{ output_dir }}/directory_a/foo.txt'
register: stat_result_a
- name: get stat information for directory_b
stat:
path: '{{ output_dir }}/directory_b/foo.txt'
register: stat_result_b
- assert:
that:
- '''changed'' in sync_result'
- sync_result.changed == true
- stat_result_a.stat.inode == stat_result_b.stat.inode
- name: synchronize files using link_dest that would be recursive
synchronize:
src: '{{output_dir}}/foo.txt'
dest: '{{output_dir}}/foo.result'
link_dest:
- '{{output_dir}}'
register: sync_result
ignore_errors: true
- assert:
that:
- sync_result is not changed
- sync_result is failed
- name: Cleanup
file:
state: absent
path: '{{output_dir}}/{{item}}'
with_items:
- directory_b/foo.txt
- directory_a/foo.txt
- directory_a
- directory_b

View File

@@ -0,0 +1,4 @@
shippable/posix/group1
skip/aix
skip/freebsd
skip/osx

View File

@@ -0,0 +1,12 @@
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
vm.swappiness=1
kernel.panic=2

View File

@@ -0,0 +1,2 @@
dependencies:
- prepare_tests

View File

@@ -0,0 +1,291 @@
# Test code for the sysctl module.
# (c) 2017, James Tanner <tanner.jc@gmail.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/>.
# NOTE: Testing sysctl inside an unprivileged container means that we cannot
# apply sysctl, or it will always fail, because of that in most cases (except
# those when it should fail) we have to use `reload=no`.
- name: Test inside Docker
when:
- ansible_facts.virtualization_type == 'docker'
block:
- set_fact:
output_dir_test: "{{ output_dir }}/test_sysctl"
- name: make sure our testing sub-directory does not exist
file:
path: "{{ output_dir_test }}"
state: absent
- name: create our testing sub-directory
file:
path: "{{ output_dir_test }}"
state: directory
##
## sysctl - file manipulation
##
- name: copy the example conf to the test dir
copy:
src: sysctl.conf
dest: "{{ output_dir_test }}"
- name: Set vm.swappiness to 5
sysctl:
name: vm.swappiness
value: 5
state: present
reload: no
sysctl_file: "{{ output_dir_test }}/sysctl.conf"
register: sysctl_test0
- debug:
var: sysctl_test0
verbosity: 1
- name: get file content
shell: "cat {{ output_dir_test }}/sysctl.conf | egrep -v ^\\#"
register: sysctl_content0
- debug:
var: sysctl_content0
verbosity: 1
- name: Set vm.swappiness to 5 again
sysctl:
name: vm.swappiness
value: 5
state: present
reload: no
sysctl_file: "{{ output_dir_test }}/sysctl.conf"
register: sysctl_test1
- name: validate results
assert:
that:
- sysctl_test0 is changed
- sysctl_test1 is not changed
- 'sysctl_content0.stdout_lines[sysctl_content0.stdout_lines.index("vm.swappiness=5")] == "vm.swappiness=5"'
- name: Remove kernel.panic
sysctl:
name: kernel.panic
value: 2
reload: no
state: absent
sysctl_file: "{{ output_dir_test }}/sysctl.conf"
register: sysctl_test2
- name: get file content
shell: "cat {{ output_dir_test }}/sysctl.conf | egrep -v ^\\#"
register: sysctl_content2
- debug:
var: item
verbosity: 1
with_items:
- "{{ sysctl_test2 }}"
- "{{ sysctl_content2 }}"
- name: Validate results for key removal
assert:
that:
- sysctl_test2 is changed
- "'kernel.panic' not in sysctl_content2.stdout_lines"
- name: Test remove kernel.panic again
sysctl:
name: kernel.panic
value: 2
state: absent
reload: no
sysctl_file: "{{ output_dir_test }}/sysctl.conf"
register: sysctl_test2_change_test
- name: Assert that no change was made
assert:
that:
- sysctl_test2_change_test is not changed
- name: Try sysctl with an invalid value
sysctl:
name: net.ipv4.ip_forward
value: foo
register: sysctl_test3
ignore_errors: yes
- debug:
var: sysctl_test3
verbosity: 1
- name: validate results for test 3
assert:
that:
- sysctl_test3 is failed
##
## sysctl - sysctl_set
##
- name: set net.ipv4.ip_forward
sysctl:
name: net.ipv4.ip_forward
value: 1
sysctl_set: yes
reload: no
register: sysctl_test3
- name: check with sysctl command
shell: sysctl net.ipv4.ip_forward
register: sysctl_check3
- debug:
var: item
verbosity: 1
with_items:
- "{{ sysctl_test3 }}"
- "{{ sysctl_check3 }}"
- name: validate results for test 3
assert:
that:
- sysctl_test3 is changed
- 'sysctl_check3.stdout_lines == ["net.ipv4.ip_forward = 1"]'
- name: Try sysctl with no name
sysctl:
name:
value: 1
sysctl_set: yes
ignore_errors: True
register: sysctl_no_name
- name: validate nameless results
assert:
that:
- sysctl_no_name is failed
- "sysctl_no_name.msg == 'name cannot be None'"
- name: Try sysctl with no value
sysctl:
name: Foo
value:
sysctl_set: yes
ignore_errors: True
register: sysctl_no_value
- name: validate nameless results
assert:
that:
- sysctl_no_value is failed
- "sysctl_no_value.msg == 'value cannot be None'"
- name: Try sysctl with an invalid value
sysctl:
name: net.ipv4.ip_forward
value: foo
sysctl_set: yes
register: sysctl_test4
ignore_errors: yes
- debug:
var: sysctl_test4
verbosity: 1
- name: validate results for test 4
assert:
that:
- sysctl_test4 is failed
- name: Test on RHEL VMs
when:
- ansible_facts.virtualization_type != 'docker'
- ansible_facts.distribution == 'RedHat'
block:
# Test reload: yes
- name: Set sysctl property using module
sysctl:
name: vm.swappiness
value: '22'
state: present
reload: yes
register: sysctl_set1
- name: Change sysctl property using command
command: sysctl vm.swappiness=33
- name: Set sysctl property using module
sysctl:
name: vm.swappiness
value: '22'
state: present
reload: yes
register: sysctl_set2
- name: Read /etc/sysctl.conf
command: 'egrep -v ^# /etc/sysctl.conf'
register: sysctl_conf_content
- name: Get current value of vm.swappiness
command: sysctl -n vm.swappiness
register: sysctl_current_vm_swappiness
- name: Ensure changes were made appropriately
assert:
that:
- sysctl_set1 is changed
- sysctl_set2 is changed
- "'vm.swappiness=22' in sysctl_conf_content.stdout_lines"
- sysctl_current_vm_swappiness.stdout == '22'
# Test reload: yes in check mode
- name: Set the same value using module in check mode
sysctl:
name: vm.swappiness
value: '22'
state: present
reload: yes
check_mode: yes
register: sysctl_check_mode1
- name: Set a different value using module in check mode
sysctl:
name: vm.swappiness
value: '44'
state: present
reload: yes
check_mode: yes
register: sysctl_check_mode2
- name: Read /etc/sysctl.conf
command: 'egrep -v ^# /etc/sysctl.conf'
register: sysctl_check_mode_conf_content
- name: Get current value of vm.swappiness
command: sysctl -n vm.swappiness
register: sysctl_check_mode_current_vm_swappiness
- name: Ensure no changes were made in check mode
assert:
that:
- sysctl_check_mode1 is success
- sysctl_check_mode2 is changed
- "'vm.swappiness=22' in sysctl_check_mode_conf_content.stdout_lines"
- sysctl_check_mode_current_vm_swappiness.stdout == '22'

4
tests/requirements.yml Normal file
View File

@@ -0,0 +1,4 @@
integration_tests_dependencies:
- community.general
unit_tests_dependencies:
- community.general

View File

@@ -0,0 +1,32 @@
plugins/module_utils/ismount.py future-import-boilerplate
plugins/module_utils/ismount.py metaclass-boilerplate
plugins/modules/acl.py validate-modules:parameter-type-not-in-doc
plugins/modules/synchronize.py pylint:blacklisted-name
plugins/modules/synchronize.py use-argspec-type-path
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
plugins/modules/synchronize.py validate-modules:parameter-list-no-elements
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
plugins/modules/synchronize.py validate-modules:undocumented-parameter
plugins/modules/at.py validate-modules:doc-required-mismatch
plugins/modules/authorized_key.py validate-modules:parameter-type-not-in-doc
plugins/modules/seboolean.py validate-modules:parameter-type-not-in-doc
plugins/modules/selinux.py validate-modules:invalid-ansiblemodule-schema
plugins/modules/selinux.py validate-modules:parameter-type-not-in-doc
plugins/modules/sysctl.py validate-modules:doc-missing-type
plugins/modules/sysctl.py validate-modules:parameter-type-not-in-doc
tests/unit/mock/path.py future-import-boilerplate
tests/unit/mock/path.py metaclass-boilerplate
tests/unit/mock/yaml_helper.py future-import-boilerplate
tests/unit/mock/yaml_helper.py metaclass-boilerplate
tests/unit/modules/conftest.py future-import-boilerplate
tests/unit/modules/conftest.py metaclass-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py future-import-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py metaclass-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py pylint:blacklisted-name
tests/unit/modules/system/test_mount.py future-import-boilerplate
tests/unit/modules/system/test_mount.py metaclass-boilerplate
tests/unit/modules/utils.py future-import-boilerplate
tests/unit/modules/utils.py metaclass-boilerplate
tests/unit/plugins/action/test_synchronize.py future-import-boilerplate
tests/unit/plugins/action/test_synchronize.py metaclass-boilerplate

View File

@@ -0,0 +1,32 @@
plugins/module_utils/ismount.py future-import-boilerplate
plugins/module_utils/ismount.py metaclass-boilerplate
plugins/modules/acl.py validate-modules:parameter-type-not-in-doc
plugins/modules/synchronize.py pylint:blacklisted-name
plugins/modules/synchronize.py use-argspec-type-path
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
plugins/modules/synchronize.py validate-modules:parameter-list-no-elements
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
plugins/modules/synchronize.py validate-modules:undocumented-parameter
plugins/modules/at.py validate-modules:doc-required-mismatch
plugins/modules/authorized_key.py validate-modules:parameter-type-not-in-doc
plugins/modules/seboolean.py validate-modules:parameter-type-not-in-doc
plugins/modules/selinux.py validate-modules:invalid-ansiblemodule-schema
plugins/modules/selinux.py validate-modules:parameter-type-not-in-doc
plugins/modules/sysctl.py validate-modules:doc-missing-type
plugins/modules/sysctl.py validate-modules:parameter-type-not-in-doc
tests/unit/mock/path.py future-import-boilerplate
tests/unit/mock/path.py metaclass-boilerplate
tests/unit/mock/yaml_helper.py future-import-boilerplate
tests/unit/mock/yaml_helper.py metaclass-boilerplate
tests/unit/modules/conftest.py future-import-boilerplate
tests/unit/modules/conftest.py metaclass-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py future-import-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py metaclass-boilerplate
tests/unit/modules/system/interfaces_file/test_interfaces_file.py pylint:blacklisted-name
tests/unit/modules/system/test_mount.py future-import-boilerplate
tests/unit/modules/system/test_mount.py metaclass-boilerplate
tests/unit/modules/utils.py future-import-boilerplate
tests/unit/modules/utils.py metaclass-boilerplate
tests/unit/plugins/action/test_synchronize.py future-import-boilerplate
tests/unit/plugins/action/test_synchronize.py metaclass-boilerplate

View File

@@ -0,0 +1,4 @@
packaging # needed for update-bundled and changelog
sphinx ; python_version >= '3.5' # docs build requires python 3+
sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+
straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+

0
tests/unit/__init__.py Normal file
View File

View File

View File

@@ -0,0 +1,33 @@
# (c) 2014, Toshio Kuratomi <tkuratomi@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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
#
# Compat for python2.7
#
# One unittest needs to import builtins via __import__() so we need to have
# the string that represents it
try:
import __builtin__
except ImportError:
BUILTINS = 'builtins'
else:
BUILTINS = '__builtin__'

122
tests/unit/compat/mock.py Normal file
View File

@@ -0,0 +1,122 @@
# (c) 2014, Toshio Kuratomi <tkuratomi@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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
'''
Compat module for Python3.x's unittest.mock module
'''
import sys
# Python 2.7
# Note: Could use the pypi mock library on python3.x as well as python2.x. It
# is the same as the python3 stdlib mock library
try:
# Allow wildcard import because we really do want to import all of mock's
# symbols into this compat shim
# pylint: disable=wildcard-import,unused-wildcard-import
from unittest.mock import *
except ImportError:
# Python 2
# pylint: disable=wildcard-import,unused-wildcard-import
try:
from mock import *
except ImportError:
print('You need the mock library installed on python2.x to run tests')
# Prior to 3.4.4, mock_open cannot handle binary read_data
if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
file_spec = None
def _iterate_read_data(read_data):
# Helper for mock_open:
# Retrieve lines from read_data via a generator so that separate calls to
# readline, read, and readlines are properly interleaved
sep = b'\n' if isinstance(read_data, bytes) else '\n'
data_as_list = [l + sep for l in read_data.split(sep)]
if data_as_list[-1] == sep:
# If the last line ended in a newline, the list comprehension will have an
# extra entry that's just a newline. Remove this.
data_as_list = data_as_list[:-1]
else:
# If there wasn't an extra newline by itself, then the file being
# emulated doesn't have a newline to end the last line remove the
# newline that our naive format() added
data_as_list[-1] = data_as_list[-1][:-1]
for line in data_as_list:
yield line
def mock_open(mock=None, read_data=''):
"""
A helper function to create a mock to replace the use of `open`. It works
for `open` called directly or used as a context manager.
The `mock` argument is the mock object to configure. If `None` (the
default) then a `MagicMock` will be created for you, with the API limited
to methods or attributes available on standard file handles.
`read_data` is a string for the `read` methoddline`, and `readlines` of the
file handle to return. This is an empty string by default.
"""
def _readlines_side_effect(*args, **kwargs):
if handle.readlines.return_value is not None:
return handle.readlines.return_value
return list(_data)
def _read_side_effect(*args, **kwargs):
if handle.read.return_value is not None:
return handle.read.return_value
return type(read_data)().join(_data)
def _readline_side_effect():
if handle.readline.return_value is not None:
while True:
yield handle.readline.return_value
for line in _data:
yield line
global file_spec
if file_spec is None:
import _io
file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
if mock is None:
mock = MagicMock(name='open', spec=open)
handle = MagicMock(spec=file_spec)
handle.__enter__.return_value = handle
_data = _iterate_read_data(read_data)
handle.write.return_value = None
handle.read.return_value = None
handle.readline.return_value = None
handle.readlines.return_value = None
handle.read.side_effect = _read_side_effect
handle.readline.side_effect = _readline_side_effect()
handle.readlines.side_effect = _readlines_side_effect
mock.return_value = handle
return mock

View File

@@ -0,0 +1,38 @@
# (c) 2014, Toshio Kuratomi <tkuratomi@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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
'''
Compat module for Python2.7's unittest module
'''
import sys
# Allow wildcard import because we really do want to import all of
# unittests's symbols into this compat shim
# pylint: disable=wildcard-import,unused-wildcard-import
if sys.version_info < (2, 7):
try:
# Need unittest2 on python2.6
from unittest2 import *
except ImportError:
print('You need unittest2 installed on python2.6.x to run tests')
else:
from unittest import *

View File

116
tests/unit/mock/loader.py Normal file
View File

@@ -0,0 +1,116 @@
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
from ansible.errors import AnsibleParserError
from ansible.parsing.dataloader import DataLoader
from ansible.module_utils._text import to_bytes, to_text
class DictDataLoader(DataLoader):
def __init__(self, file_mapping=None):
file_mapping = {} if file_mapping is None else file_mapping
assert type(file_mapping) == dict
super(DictDataLoader, self).__init__()
self._file_mapping = file_mapping
self._build_known_directories()
self._vault_secrets = None
def load_from_file(self, path, cache=True, unsafe=False):
path = to_text(path)
if path in self._file_mapping:
return self.load(self._file_mapping[path], path)
return None
# TODO: the real _get_file_contents returns a bytestring, so we actually convert the
# unicode/text it's created with to utf-8
def _get_file_contents(self, path):
path = to_text(path)
if path in self._file_mapping:
return (to_bytes(self._file_mapping[path]), False)
else:
raise AnsibleParserError("file not found: %s" % path)
def path_exists(self, path):
path = to_text(path)
return path in self._file_mapping or path in self._known_directories
def is_file(self, path):
path = to_text(path)
return path in self._file_mapping
def is_directory(self, path):
path = to_text(path)
return path in self._known_directories
def list_directory(self, path):
ret = []
path = to_text(path)
for x in (list(self._file_mapping.keys()) + self._known_directories):
if x.startswith(path):
if os.path.dirname(x) == path:
ret.append(os.path.basename(x))
return ret
def is_executable(self, path):
# FIXME: figure out a way to make paths return true for this
return False
def _add_known_directory(self, directory):
if directory not in self._known_directories:
self._known_directories.append(directory)
def _build_known_directories(self):
self._known_directories = []
for path in self._file_mapping:
dirname = os.path.dirname(path)
while dirname not in ('/', ''):
self._add_known_directory(dirname)
dirname = os.path.dirname(dirname)
def push(self, path, content):
rebuild_dirs = False
if path not in self._file_mapping:
rebuild_dirs = True
self._file_mapping[path] = content
if rebuild_dirs:
self._build_known_directories()
def pop(self, path):
if path in self._file_mapping:
del self._file_mapping[path]
self._build_known_directories()
def clear(self):
self._file_mapping = dict()
self._known_directories = []
def get_basedir(self):
return os.getcwd()
def set_vault_secrets(self, vault_secrets):
self._vault_secrets = vault_secrets

5
tests/unit/mock/path.py Normal file
View File

@@ -0,0 +1,5 @@
from ansible_collections.ansible.posix.tests.unit.compat.mock import MagicMock
from ansible.utils.path import unfrackpath
mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)

View File

@@ -0,0 +1,90 @@
# (c) 2016, Matt Davis <mdavis@ansible.com>
# (c) 2016, Toshio Kuratomi <tkuratomi@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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import sys
import json
from contextlib import contextmanager
from io import BytesIO, StringIO
from ansible_collections.ansible.posix.tests.unit.compat import unittest
from ansible.module_utils.six import PY3
from ansible.module_utils._text import to_bytes
@contextmanager
def swap_stdin_and_argv(stdin_data='', argv_data=tuple()):
"""
context manager that temporarily masks the test runner's values for stdin and argv
"""
real_stdin = sys.stdin
real_argv = sys.argv
if PY3:
fake_stream = StringIO(stdin_data)
fake_stream.buffer = BytesIO(to_bytes(stdin_data))
else:
fake_stream = BytesIO(to_bytes(stdin_data))
try:
sys.stdin = fake_stream
sys.argv = argv_data
yield
finally:
sys.stdin = real_stdin
sys.argv = real_argv
@contextmanager
def swap_stdout():
"""
context manager that temporarily replaces stdout for tests that need to verify output
"""
old_stdout = sys.stdout
if PY3:
fake_stream = StringIO()
else:
fake_stream = BytesIO()
try:
sys.stdout = fake_stream
yield fake_stream
finally:
sys.stdout = old_stdout
class ModuleTestCase(unittest.TestCase):
def setUp(self, module_args=None):
if module_args is None:
module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False}
args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
# unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
self.stdin_swap.__enter__()
def tearDown(self):
# unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
self.stdin_swap.__exit__(None, None, None)

View File

@@ -0,0 +1,39 @@
# 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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils._text import to_bytes
from ansible.parsing.vault import VaultSecret
class TextVaultSecret(VaultSecret):
'''A secret piece of text. ie, a password. Tracks text encoding.
The text encoding of the text may not be the default text encoding so
we keep track of the encoding so we encode it to the same bytes.'''
def __init__(self, text, encoding=None, errors=None, _bytes=None):
super(TextVaultSecret, self).__init__()
self.text = text
self.encoding = encoding or 'utf-8'
self._bytes = _bytes
self.errors = errors or 'strict'
@property
def bytes(self):
'''The text encoded with encoding, unless we specifically set _bytes.'''
return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)

View File

@@ -0,0 +1,121 @@
import io
import yaml
from ansible.module_utils.six import PY3
from ansible.parsing.yaml.loader import AnsibleLoader
from ansible.parsing.yaml.dumper import AnsibleDumper
class YamlTestUtils(object):
"""Mixin class to combine with a unittest.TestCase subclass."""
def _loader(self, stream):
"""Vault related tests will want to override this.
Vault cases should setup a AnsibleLoader that has the vault password."""
return AnsibleLoader(stream)
def _dump_stream(self, obj, stream, dumper=None):
"""Dump to a py2-unicode or py3-string stream."""
if PY3:
return yaml.dump(obj, stream, Dumper=dumper)
else:
return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
def _dump_string(self, obj, dumper=None):
"""Dump to a py2-unicode or py3-string"""
if PY3:
return yaml.dump(obj, Dumper=dumper)
else:
return yaml.dump(obj, Dumper=dumper, encoding=None)
def _dump_load_cycle(self, obj):
# Each pass though a dump or load revs the 'generation'
# obj to yaml string
string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
# wrap a stream/file like StringIO around that yaml
stream_from_object_dump = io.StringIO(string_from_object_dump)
loader = self._loader(stream_from_object_dump)
# load the yaml stream to create a new instance of the object (gen 2)
obj_2 = loader.get_data()
# dump the gen 2 objects directory to strings
string_from_object_dump_2 = self._dump_string(obj_2,
dumper=AnsibleDumper)
# The gen 1 and gen 2 yaml strings
self.assertEqual(string_from_object_dump, string_from_object_dump_2)
# the gen 1 (orig) and gen 2 py object
self.assertEqual(obj, obj_2)
# again! gen 3... load strings into py objects
stream_3 = io.StringIO(string_from_object_dump_2)
loader_3 = self._loader(stream_3)
obj_3 = loader_3.get_data()
string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
self.assertEqual(obj, obj_3)
# should be transitive, but...
self.assertEqual(obj_2, obj_3)
self.assertEqual(string_from_object_dump, string_from_object_dump_3)
def _old_dump_load_cycle(self, obj):
'''Dump the passed in object to yaml, load it back up, dump again, compare.'''
stream = io.StringIO()
yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
self._dump_stream(obj, stream, dumper=AnsibleDumper)
yaml_string_from_stream = stream.getvalue()
# reset stream
stream.seek(0)
loader = self._loader(stream)
# loader = AnsibleLoader(stream, vault_password=self.vault_password)
obj_from_stream = loader.get_data()
stream_from_string = io.StringIO(yaml_string)
loader2 = self._loader(stream_from_string)
# loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
obj_from_string = loader2.get_data()
stream_obj_from_stream = io.StringIO()
stream_obj_from_string = io.StringIO()
if PY3:
yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
else:
yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None)
yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None)
yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
stream_obj_from_stream.seek(0)
stream_obj_from_string.seek(0)
if PY3:
yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
else:
yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None)
yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None)
assert yaml_string == yaml_string_obj_from_stream
assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream ==
yaml_string_stream_obj_from_string)
assert obj == obj_from_stream
assert obj == obj_from_string
assert obj == yaml_string_obj_from_stream
assert obj == yaml_string_obj_from_string
assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
return {'obj': obj,
'yaml_string': yaml_string,
'yaml_string_from_stream': yaml_string_from_stream,
'obj_from_stream': obj_from_stream,
'obj_from_string': obj_from_string,
'yaml_string_obj_from_string': yaml_string_obj_from_string}

View File

View File

@@ -0,0 +1,28 @@
# Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import json
import pytest
from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping
@pytest.fixture
def patch_ansible_module(request, mocker):
if isinstance(request.param, string_types):
args = request.param
elif isinstance(request.param, MutableMapping):
if 'ANSIBLE_MODULE_ARGS' not in request.param:
request.param = {'ANSIBLE_MODULE_ARGS': request.param}
if '_ansible_remote_tmp' not in request.param['ANSIBLE_MODULE_ARGS']:
request.param['ANSIBLE_MODULE_ARGS']['_ansible_remote_tmp'] = '/tmp'
if '_ansible_keep_remote_files' not in request.param['ANSIBLE_MODULE_ARGS']:
request.param['ANSIBLE_MODULE_ARGS']['_ansible_keep_remote_files'] = False
args = json.dumps(request.param)
else:
raise Exception('Malformed data to the patch_ansible_module pytest fixture')
mocker.patch('ansible.module_utils.basic._ANSIBLE_ARGS', to_bytes(args))

View File

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,8 @@
[0] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "up",
"state": "present",
"value": "route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi"
}

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,17 @@
[0] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "up",
"state": "present",
"value": "route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi"
}
=====
[1] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "up",
"state": "absent",
"value": null
}

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.42
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,13 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
post-up XXXX_ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,13 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
pre-up XXXX_ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::42
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,13 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6
post-up XXXX_ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,13 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6
pre-up XXXX_ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,8 @@
fail_json message: Error: interface eth1 not found
options:
{
"iface": "eth1",
"option": "method",
"state": "present",
"value": "dhcp"
}

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,13 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6
mtu 1350

View File

@@ -0,0 +1,8 @@
[0] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "mtu",
"state": "present",
"value": "1350"
}

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,12 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet static
address 192.168.0.1
post-up echo configuring ipv4
iface eth0 inet6 static
address fc00::1
post-up echo configuring ipv6

View File

@@ -0,0 +1,8 @@
[0] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "slaves",
"state": "present",
"value": "int1 int3"
}

View File

@@ -0,0 +1,21 @@
{
"eth0": {
"address": "fc00::1",
"address_family": "inet6",
"down": [],
"method": "static",
"post-up": [
"echo configuring ipv6"
],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,6 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet dhcp

View File

@@ -0,0 +1,18 @@
{
"eth0": {
"address_family": "inet",
"down": [],
"method": "dhcp",
"post-up": [],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

View File

@@ -0,0 +1,6 @@
# The loopback network interface
auto lo eth0
iface lo inet loopback
# The primary network interface
iface eth0 inet dhcp

View File

@@ -0,0 +1,8 @@
[0] fail_json message: Error: interface aggi not found
options:
{
"iface": "aggi",
"option": "up",
"state": "present",
"value": "route add -net 224.0.0.0 netmask 240.0.0.0 dev aggi"
}

View File

@@ -0,0 +1,18 @@
{
"eth0": {
"address_family": "inet",
"down": [],
"method": "dhcp",
"post-up": [],
"pre-up": [],
"up": []
},
"lo": {
"address_family": "inet",
"down": [],
"method": "loopback",
"post-up": [],
"pre-up": [],
"up": []
}
}

Some files were not shown because too many files have changed in this diff Show More