ansible.posix
ansible.posix copied to clipboard
`sysctl` module replaces symlink with a real file
SUMMARY
When the destination file for the sysctl
module is a symlink, the module will replace that symlink with a real file. All other content in the file is carried forward, as expected. However, but I would have expected the symlink to be left and destination of the symlink instead be modified.
Alternatively, if the module included the follow: true
parameter (as does the copy
module), then the behavior would be clear and expected.
FWIW, this sounds VERY similar to https://github.com/ansible/ansible/issues/49809.
ISSUE TYPE
- Bug Report
COMPONENT NAME
Compnent: ansible.posix.sysctl
ANSIBLE VERSION
ansible 2.9.12
config file = /Users/me/Projects/sysops/ansible/ansible.cfg
configured module search path = ['/Users/me/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /Users/me/Projects/sysops/ansible/.venv/lib/python3.8/site-packages/ansible
executable location = /Users/me/Projects/sysops/ansible/.venv/bin/ansible
python version = 3.8.6 (default, Oct 8 2020, 14:06:32) [Clang 12.0.0 (clang-1200.0.32.2)]
CONFIGURATION
<none>
OS / ENVIRONMENT
Ansible node:
$ uname -a
Darwin myhost 19.6.0 Darwin Kernel Version 19.6.0: Thu Oct 29 22:56:45 PDT 2020; root:xnu-6153.141.2.2~1/RELEASE_X86_64 x86_64 i386 MacBookPro16,1 Darwin
Target machine:
$ uname -a
Linux testhost.example.com 4.15.0-111-generic #112-Ubuntu SMP Thu Jul 9 20:32:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/issue
Ubuntu 18.04.5 LTS \n \l
STEPS TO REPRODUCE
Run the following playbook:
- hosts: all
become: True
tags:
- sysctl_bug
vars:
sysctl_var: 'kernel.randomize_va_space'
sysctl_val: '1'
sysctl_file: /tmp/ansible_sysctl_test.conf
sysctl_link: /tmp/ansible_sysctl_test_symlink.conf
tasks:
- command:
cmd: "sysctl {{ sysctl_var }}"
register: sysctl_current_value
changed_when: false
- debug:
var: sysctl_current_value.stdout
- copy:
content: |
# Testing Ansible Sysctl module bug
{{ sysctl_current_value.stdout }}
dest: "{{ sysctl_file }}"
- file:
src: "{{ sysctl_file }}"
dest: "{{ sysctl_link }}"
state: link
- stat:
path: "{{ sysctl_link }}"
register: stat_result
- assert:
that:
- stat_result.stat.islnk is defined and stat_result.stat.islnk
- stat_result.stat.lnk_source == "{{ sysctl_file }}"
success_msg: "{{ sysctl_link }} is correct symlink"
fail_msg: "{{ sysctl_link }} is NOT correct symlink"
# This is the real point of all of this.
# This call will replace the symlink with a real file!
- name: sysctl | enable randomized layout of virtual address space
sysctl:
name: "{{ sysctl_var }}"
value: "{{ sysctl_val }}"
sysctl_file: "{{ sysctl_link }}"
state: present
sysctl_set: no
reload: no
# follow: true # if only this existed, like it does for `copy` module.
- stat:
path: "{{ sysctl_link }}"
register: stat_result
- assert:
that:
- stat_result.stat.islnk is defined and stat_result.stat.islnk
- stat_result.stat.lnk_source == "{{ sysctl_file }}"
success_msg: "{{ sysctl_link }} is correct symlink"
fail_msg: "{{ sysctl_link }} is NOT correct symlink"
EXPECTED RESULTS
From the above playbook, the output should end with:
myhost $ ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook playbooks/sysctl-bug.yml -v -l testhost
[... elided ...]
TASK [assert] ***********************************************************************
ok: [testhost] => changed=false
msg: /tmp/ansible_sysctl_test_symlink.conf is correct symlink
[... elided ...]
ACTUAL RESULTS
From the above playbook, the output actually is:
Using /Users/me/Projects/sysops/ansible/ansible.cfg as config file
PLAY [all] **************************************************************************
TASK [command] **********************************************************************
ok: [testhost] => changed=false
cmd:
- sysctl
- kernel.randomize_va_space
delta: '0:00:00.004009'
end: '2020-11-13 13:44:43.103807'
rc: 0
start: '2020-11-13 13:44:43.099798'
stderr: ''
stderr_lines: <omitted>
stdout: kernel.randomize_va_space = 2
stdout_lines: <omitted>
TASK [debug] ************************************************************************
ok: [testhost] =>
sysctl_current_value.stdout: kernel.randomize_va_space = 2
TASK [copy] *************************************************************************
changed: [testhost] => changed=true
checksum: 61c723791d6e16434a434bc25a22f1f6f9f37d8c
dest: /tmp/ansible_sysctl_test.conf
gid: 0
group: root
md5sum: cbcb1718a024d5175fed6d728d7bc65d
mode: '0600'
owner: root
size: 66
src: /home/ede/.ansible/tmp/ansible-tmp-1605296683.776194-20285-115510499115130/source
state: file
uid: 0
TASK [file] *************************************************************************
changed: [testhost] => changed=true
dest: /tmp/ansible_sysctl_test_symlink.conf
gid: 0
group: root
mode: '0777'
owner: root
size: 29
src: /tmp/ansible_sysctl_test.conf
state: link
uid: 0
TASK [stat] *************************************************************************
ok: [testhost] => changed=false
stat:
atime: 1605296688.136057
attr_flags: ''
attributes: []
block_size: 4096
blocks: 0
charset: binary
ctime: 1605296688.136057
dev: 64769
device_type: 0
executable: false
exists: true
gid: 0
gr_name: root
inode: 82575387
isblk: false
ischr: false
isdir: false
isfifo: false
isgid: false
islnk: true
isreg: false
issock: false
isuid: false
lnk_source: /tmp/ansible_sysctl_test.conf
lnk_target: /tmp/ansible_sysctl_test.conf
mimetype: inode/symlink
mode: '0777'
mtime: 1605296688.136057
nlink: 1
path: /tmp/ansible_sysctl_test_symlink.conf
pw_name: root
readable: true
rgrp: true
roth: true
rusr: true
size: 29
uid: 0
version: null
wgrp: true
woth: true
writeable: true
wusr: true
xgrp: true
xoth: true
xusr: true
TASK [assert] ***********************************************************************
ok: [testhost] => changed=false
msg: /tmp/ansible_sysctl_test_symlink.conf is correct symlink
TASK [sysctl | enable randomized layout of virtual address space] *******************
changed: [testhost] => changed=true
TASK [stat] *************************************************************************
ok: [testhost] => changed=false
stat:
atime: 1605296691.6320832
attr_flags: e
attributes:
- extents
block_size: 4096
blocks: 8
charset: us-ascii
checksum: b7782f78820c1a7478900fd658b5f93a85a18253
ctime: 1605296691.6320832
dev: 64769
device_type: 0
executable: false
exists: true
gid: 0
gr_name: root
inode: 82575388
isblk: false
ischr: false
isdir: false
isfifo: false
isgid: false
islnk: false
isreg: true
issock: false
isuid: false
mimetype: text/plain
mode: '0600'
mtime: 1605296691.6320832
nlink: 1
path: /tmp/ansible_sysctl_test_symlink.conf
pw_name: root
readable: true
rgrp: false
roth: false
rusr: true
size: 64
uid: 0
version: '563617165'
wgrp: false
woth: false
writeable: true
wusr: true
xgrp: false
xoth: false
xusr: false
TASK [assert] ***********************************************************************
fatal: [testhost]: FAILED! => changed=false
assertion: stat_result.stat.islnk is defined and stat_result.stat.islnk
evaluated_to: false
msg: /tmp/ansible_sysctl_test_symlink.conf is NOT correct symlink
PLAY RECAP **************************************************************************
testhost : ok=8 changed=3 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0