ansible.posix icon indicating copy to clipboard operation
ansible.posix copied to clipboard

`sysctl` module replaces symlink with a real file

Open eengstrom opened this issue 3 years ago • 0 comments

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   

eengstrom avatar Nov 13 '20 20:11 eengstrom