---
- name: Set version specific variables
  include_tasks: tasks/set_vars.yml

- name: Populate service facts
  service_facts:

- name: Set variable `timesync_services` with filtered uniq service names
  set_fact:
    timesync_services: "{{ ansible_facts.services.values() |
          selectattr('name', 'defined') |
          selectattr('status', 'defined') |
          rejectattr('status', 'match', '^not-found$') |
          rejectattr('status', 'match', '^masked$') |
          rejectattr('status', 'match', '^failed$') |
          map(attribute='name') |
          map('regex_replace', '[.]service.*$', '') |
          map('regex_replace', '@$', '') |
          unique |
          list }}"

- name: Check that variable 'timesync_services' is defined
  assert:
    that: timesync_services is defined
    fail_msg: "Variable 'timesync_services' is not defined"

- name: Check if only NTP is needed
  set_fact:
    timesync_mode: 1
  when: timesync_ptp_domains | length == 0

- name: Check if single PTP is needed
  set_fact:
    timesync_mode: 2
  when:
    - timesync_mode is not defined
    - timesync_ntp_servers | length == 0
    - timesync_ptp_domains | length == 1
    - timesync_ptp_domains[0].interfaces | length == 1

- name: Check if both NTP and PTP are needed
  set_fact:
    timesync_mode: 3
  when: timesync_mode is not defined

- name: Determine current NTP provider
  timesync_provider:  # noqa fqcn[action]
  when:
    - timesync_mode != 2
    - timesync_ntp_provider | length == 0

- name: Select NTP provider
  set_fact:
    timesync_ntp_provider: "{{
        timesync_ntp_provider_current |
        default(timesync_ntp_provider_os_default, true) }}"
  when:
    - timesync_mode != 2
    - timesync_ntp_provider | length == 0

- name: Install chrony
  package:
    name: chrony
    state: present
    use: "{{ (__timesync_is_ostree | d(false)) |
             ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
  when:
    - timesync_mode != 2
    - timesync_ntp_provider == 'chrony'
  register: timesync_chrony_result

- name: Install ntp
  package:
    name: ntp
    state: present
    use: "{{ (__timesync_is_ostree | d(false)) |
             ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
  when:
    - timesync_mode != 2
    - timesync_ntp_provider == 'ntp'
  register: timesync_ntp_result

- name: Install linuxptp
  package:
    name: linuxptp
    state: present
    use: "{{ (__timesync_is_ostree | d(false)) |
             ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
  when: timesync_mode != 1
  register: timesync_linuxptp_result

- name: Handle reboot for transactional update systems
  when:
    - __timesync_is_transactional | d(false)
    - timesync_chrony_result is changed or
      timesync_ntp_result is changed or
      timesync_linuxptp_result is changed
  block:
    - name: Notify user that reboot is needed to apply changes
      debug:
        msg: >
          Reboot required to apply changes due to transactional updates.

    - name: Reboot transactional update systems
      reboot:
        msg: Rebooting the system to apply transactional update changes.
      when: timesync_transactional_update_reboot_ok | bool

    - name: Fail if reboot is needed and not set
      fail:
        msg: >
          Reboot is required but not allowed. Please set
          'timesync_transactional_update_reboot_ok' to proceed.
      when:
        - timesync_transactional_update_reboot_ok is none

- name: Gather package facts
  package_facts:
    manager: auto

- name: Run phc_ctl on PTP interface
  command: phc_ctl -q {{ timesync_ptp_domains[0].interfaces[0] }}
  register: timesync_phc_ctl_output
  changed_when: false
  check_mode: false
  when: timesync_mode == 2
  ignore_errors: true

- name: Check if PTP interface supports HW timestamping
  set_fact:
    timesync_mode2_hwts: "{{ timesync_phc_ctl_output.rc == 0 }}"
  when: timesync_mode == 2

- name: Generate chrony.conf file
  template:
    src: chrony.conf.j2
    dest: "{{ timesync_chrony_conf_path }}"
    backup: true
    mode: "0644"
  # wokeignore:rule=master
  notify: Restart {{ 'chronyd' if timesync_mode == 1 else 'timemaster' }}
  when:
    - timesync_mode != 2
    - timesync_ntp_provider == 'chrony'
    - "'chrony' in ansible_facts.packages"

- name: Generate chronyd sysconfig file
  template:
    src: chronyd.sysconfig.j2
    dest: "{{ timesync_chrony_sysconfig_path }}"
    backup: true
    mode: "0644"
  notify: Restart chronyd
  when:
    - timesync_mode == 1
    - timesync_ntp_provider == 'chrony'
    - "'chrony' in ansible_facts.packages"

- name: Generate ntp.conf file
  template:
    src: ntp.conf.j2
    dest: /etc/ntp.conf
    backup: true
    mode: "0644"
  # wokeignore:rule=master
  notify: Restart {{ 'ntpd' if timesync_mode == 1 else 'timemaster' }}
  when:
    - timesync_mode != 2
    - timesync_ntp_provider == 'ntp'
    - "'ntp' in ansible_facts.packages"

- name: Generate ntpd sysconfig file
  template:
    src: ntpd.sysconfig.j2
    dest: "{{ timesync_ntp_sysconfig_path }}"
    backup: true
    mode: "0644"
  notify: Restart ntpd
  when:
    - timesync_mode == 1
    - timesync_ntp_provider == 'ntp'
    - "'ntp' in ansible_facts.packages"

- name: Generate ptp4l.conf file
  template:
    src: ptp4l.conf.j2
    dest: /etc/ptp4l.conf
    backup: true
    mode: "0644"
  notify: Restart ptp4l
  when:
    - timesync_mode == 2
    - "'linuxptp' in ansible_facts.packages"

- name: Generate ptp4l sysconfig file
  template:
    src: ptp4l.sysconfig.j2
    dest: "{{ timesync_ptp4l_sysconfig_path }}"
    backup: true
    mode: "0644"
  notify: Restart ptp4l
  when:
    - timesync_mode == 2
    - "'linuxptp' in ansible_facts.packages"
    - timesync_ptp4l_sysconfig_path | length > 0

- name: Generate phc2sys sysconfig file
  template:
    src: phc2sys.sysconfig.j2
    dest: /etc/sysconfig/phc2sys
    backup: true
    mode: "0644"
  notify: Restart phc2sys
  when:
    - timesync_mode == 2
    - timesync_mode2_hwts
    - "'linuxptp' in ansible_facts.packages"
    - timesync_phc2sys_sysconfig_path | length > 0

# wokeignore:rule=master
- name: Generate timemaster.conf file
  template:
    # wokeignore:rule=master
    src: timemaster.conf.j2
    # wokeignore:rule=master
    dest: "{{ timesync_timemaster_config_path }}"
    backup: true
    mode: "0644"
  # wokeignore:rule=master
  notify: Restart timemaster
  when:
    - timesync_mode == 3
    - "'linuxptp' in ansible_facts.packages"

- name: Update network sysconfig file
  lineinfile:
    dest: /etc/sysconfig/network
    create: true
    backup: true
    mode: "0644"
    regexp: '^PEERNTP='
    line: 'PEERNTP=no'
    # yamllint disable-line rule:line-length
    state: "{{ 'absent' if timesync_dhcp_ntp_servers else 'present' }}"  # noqa args[module]
  notify: Restart {{ timesync_ntp_provider + 'd' }}
  when:
    - timesync_mode == 1
    - ansible_facts['os_family'] == 'RedHat'

- name: Disable chronyd
  service:
    name: chronyd
    state: stopped
    enabled: false
  when:
    - timesync_mode != 1 or timesync_ntp_provider != 'chrony'
    - "'chronyd' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service chronyd:')

- name: Disable ntpd
  service:
    name: ntpd
    state: stopped
    enabled: false
  when:
    - timesync_mode != 1 or timesync_ntp_provider != 'ntp'
    - "'ntpd' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service ntpd:')

- name: Disable ntpdate
  service:
    name: ntpdate
    state: stopped
    enabled: false
  when: "'ntpdate' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service ntpdate:')

- name: Disable sntp
  service:
    name: sntp
    state: stopped
    enabled: false
  when: "'sntp' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service sntp:')

- name: Disable ptp4l
  service:
    name: ptp4l
    state: stopped
    enabled: false
  when:
    - timesync_mode != 2
    - "'ptp4l' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service ptp4l:')

- name: Disable phc2sys
  service:
    name: phc2sys
    state: stopped
    enabled: false
  when:
    - timesync_mode != 2 or not timesync_mode2_hwts
    - "'phc2sys' in timesync_services"
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service phc2sys:')

# wokeignore:rule=master
- name: Disable timemaster
  vars:
    # wokeignore:rule=master
    __timemstr: timemaster
  service:
    name: "{{ __timemstr }}"
    state: stopped
    enabled: false
  when:
    - timesync_mode != 3
    - __timemstr in timesync_services
  register: __disable_result
  failed_when:
    - __disable_result is failed
    - not __disable_result.msg is match(
      'Could not find the requested service ' ~ __timemstr ~ ':')

- name: Enable chronyd
  service:
    name: chronyd
    state: started
    enabled: true
  when:
    - timesync_mode == 1
    - timesync_ntp_provider == 'chrony'

- name: Enable ntpd
  service:
    name: ntpd
    state: started
    enabled: true
  when:
    - timesync_mode == 1
    - timesync_ntp_provider == 'ntp'

- name: Enable ptp4l
  service:
    name: ptp4l
    state: started
    enabled: true
  when: timesync_mode == 2

- name: Enable phc2sys
  service:
    name: phc2sys
    state: started
    enabled: true
  when:
    - timesync_mode == 2
    - timesync_mode2_hwts

# wokeignore:rule=master
- name: Enable timemaster
  service:
    # wokeignore:rule=master
    name: timemaster
    state: started
    enabled: true
  when: timesync_mode == 3
