--- - name: Remove scroll24 script and cron references hosts: all gather_facts: no vars: ssh_user: "{{ ansible_user | default('root') }}" ssh_pass: "{{ ansible_password | default(ansible_ssh_pass) }}" remote_script: "/root/scroll24.sh" remote_crontab: "/etc/crontabs/root" tmp_cron_new: "/tmp/cron.root.new" crontab_backup_dir: "/etc/crontabs" # RabbitMQ (same contract you use elsewhere) rmq_host: "{{ lookup('env','RMQ_HOST') | default('10.210.12.2', true) }}" rmq_port: "{{ lookup('env','RMQ_PORT') | default('15672', true) }}" rmq_user: "{{ lookup('env','RMQ_USER') | default('admin', true) }}" rmq_pass: "{{ lookup('env','RMQ_PASS') | default('change_me', true) }}" rmq_vhost: "{{ lookup('env','RMQ_VHOST') | default('app', true) }}" rmq_exchange: "{{ lookup('env','RMQ_EXCHANGE') | default('controls', true) }}" control_queue: "{{ lookup('env','CONTROL_QUEUE') | default('queue_controls', true) }}" tasks: ########################################################################## # 1) Make sure crontab file exists (don’t create noise) ########################################################################## - name: Ensure crontab file exists (with perms) raw: | if [ ! -f {{ remote_crontab }} ]; then touch {{ remote_crontab }}; fi chown root:root {{ remote_crontab }}; chmod 0644 {{ remote_crontab }}; changed_when: false ########################################################################## # 2) Check whether any scroll24 entries exist ########################################################################## - name: Detect existing scroll24 lines raw: "grep -F 'scroll24.sh' {{ remote_crontab }} || true" register: cron_subset changed_when: false failed_when: false - name: Decide if crontab needs cleanup set_fact: crontab_changed: "{{ (cron_subset.stdout | trim) != '' }}" - name: Backup current crontab (timestamped) when: crontab_changed | bool raw: "cp -a {{ remote_crontab }} {{ crontab_backup_dir }}/root.bak.$(date +%Y%m%d%H%M%S)" changed_when: true - name: Remove scroll24 lines from crontab (preserve others; tidy EOF) when: crontab_changed | bool raw: "grep -v 'scroll24\\.sh' {{ remote_crontab }} > {{ tmp_cron_new }} && awk 'BEGIN{for(i=1;i<=NR;i++)a[i]=$0} {a[NR]=$0} END{e=NR; while(e>0 && a[e] ~ /^[[:space:]]*$/){e--}; for(i=1;i<=e;i++) print a[i]}' {{ tmp_cron_new }} > {{ tmp_cron_new }}.trim && mv {{ tmp_cron_new }}.trim {{ tmp_cron_new }} && printf '\\n' >> {{ tmp_cron_new }} && mv {{ tmp_cron_new }} {{ remote_crontab }} && chown root:root {{ remote_crontab }} && chmod 0644 {{ remote_crontab }}" changed_when: true ########################################################################## # 3) Remove /root/scroll24.sh if present ########################################################################## - name: Check if /root/scroll24.sh exists raw: "[ -f {{ remote_script }} ] && echo PRESENT || echo ABSENT" register: script_check changed_when: false - name: Remove /root/scroll24.sh when: (script_check.stdout | trim) == 'PRESENT' raw: "rm -f {{ remote_script }}" register: rm_script changed_when: true - name: Flag script_removed set_fact: script_removed: "{{ ((script_check.stdout | trim) == 'PRESENT') }}" ########################################################################## # 4) If crontab changed, restart crond (with :51–:59 guard) ########################################################################## - name: Get current seconds when: crontab_changed | bool raw: "date +%S" register: nowsec changed_when: false - name: Sleep 10s if seconds 51-59 when: crontab_changed | bool and (nowsec.stdout | int >= 51) pause: seconds: 10 - name: Restart crond via move/move when: crontab_changed | bool raw: "mv /tmp/launchd/services/crond /root/crond && sleep 1 && mv /root/crond /tmp/launchd/services/crond" register: crond_restart changed_when: true failed_when: false - name: Verify crond is running when: crontab_changed | bool raw: "pgrep -f '/usr/sbin/crond' || busybox pgrep crond || echo missing" register: crond_pid changed_when: false failed_when: false ########################################################################## # 5) Journal + reset custom field ########################################################################## - name: Publish removal journal to control queue delegate_to: localhost uri: url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost | urlencode }}/{{ rmq_exchange | urlencode }}/publish" method: POST user: "{{ rmq_user }}" password: "{{ rmq_pass }}" force_basic_auth: true status_code: 200 headers: { content-type: "application/json" } body_format: json body: properties: { content_type: "application/json" } routing_key: "{{ control_queue }}" payload: "{{ { 'inscope_device': (ansible_hostname | default(inventory_hostname)), 'task_name': 'journal_add', 'task_result': ( 'scroll24: removal — ' ~ (crontab_changed | ternary('crontab cleaned; ', 'no crontab refs; ')) ~ (script_removed | ternary('script deleted; ', 'script not present; ')) ~ (crontab_changed | ternary('crond restarted', 'crond unchanged')) ) } | to_json }}" payload_encoding: "string" changed_when: false - name: Clear NetBox custom field scroll24 delegate_to: localhost uri: url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost | urlencode }}/{{ rmq_exchange | urlencode }}/publish" method: POST user: "{{ rmq_user }}" password: "{{ rmq_pass }}" force_basic_auth: true status_code: 200 headers: { content-type: "application/json" } body_format: json body: properties: { content_type: "application/json" } routing_key: "{{ control_queue }}" payload: "{{ { 'inscope_device': (ansible_hostname | default(inventory_hostname)), 'task_name': 'custom_field_set', 'task_add1': 'scroll24', 'task_result': 'nomore' } | to_json }}" payload_encoding: "string" changed_when: false