# Setup by setup_rpm_repo
- set_fact:
    package1: dinginessentail
    package2: dinginessentail-olive

# UNINSTALL
- name: uninstall {{ package1 }}
  yum: name={{ package1 }} state=removed
  register: yum_result

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}
  ignore_errors: True
  register: rpm_result

- name: verify uninstallation of {{ package1 }}
  assert:
    that:
        - "yum_result is success"
        - "rpm_result is failed"

# UNINSTALL AGAIN
- name: uninstall {{ package1 }} again in check mode
  yum: name={{ package1 }} state=removed
  check_mode: true
  register: yum_result

- name: verify no change on re-uninstall in check mode
  assert:
    that:
        - "not yum_result is changed"

- name: uninstall {{ package1 }} again
  yum: name={{ package1 }} state=removed
  register: yum_result

- name: verify no change on re-uninstall
  assert:
    that:
        - "not yum_result is changed"

# INSTALL
- name: install {{ package1 }} in check mode
  yum: name={{ package1 }} state=present
  check_mode: true
  register: yum_result

- name: verify installation of {{ package1 }} in check mode
  assert:
    that:
        - "yum_result is changed"

- name: install {{ package1 }}
  yum: name={{ package1 }} state=present
  register: yum_result

- name: verify installation of {{ package1 }}
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}

# INSTALL AGAIN
- name: install {{ package1 }} again in check mode
  yum: name={{ package1 }} state=present
  check_mode: true
  register: yum_result
- name: verify no change on second install in check mode
  assert:
    that:
        - "not yum_result is changed"

- name: install {{ package1 }} again
  yum: name={{ package1 }} state=present
  register: yum_result
- name: verify no change on second install
  assert:
    that:
        - "not yum_result is changed"

- name: install {{ package1 }} again with empty string enablerepo
  yum: name={{ package1 }} state=present enablerepo=""
  register: yum_result
- name: verify no change on third install with empty string enablerepo
  assert:
    that:
        - "yum_result is success"
        - "not yum_result is changed"

# This test case is unfortunately distro specific because we have to specify
# repo names which are not the same across Fedora/RHEL/CentOS for base/updates
- name: install {{ package1 }} again with missing repo enablerepo
  yum:
    name: '{{ package1 }}'
    state: present
    enablerepo: '{{ repos + ["thisrepodoesnotexist"] }}'
    disablerepo: "*"
  register: yum_result
  when: ansible_distribution == 'CentOS'
- name: verify no change on fourth install with missing repo enablerepo (yum)
  assert:
    that:
        - "yum_result is success"
        - "yum_result is not changed"
  when: ansible_distribution == 'CentOS'

# This test case is unfortunately distro specific because we have to specify
# repo names which are not the same across Fedora/RHEL/CentOS for base/updates
- name: install repos again with disable all and enable select repo(s)
  yum:
    name: '{{ package1 }}'
    state: present
    enablerepo: '{{ repos }}'
    disablerepo: "*"
  register: yum_result
  when: ansible_distribution == 'CentOS'
- name: verify no change on fourth install with missing repo enablerepo (yum)
  assert:
    that:
        - "yum_result is success"
        - "yum_result is not changed"
  when: ansible_distribution == 'CentOS'

- name: install {{ package1 }} again with only missing repo enablerepo
  yum:
    name: '{{ package1 }}'
    state: present
    enablerepo: "thisrepodoesnotexist"
  ignore_errors: true
  register: yum_result
- name: verify no change on fifth install with only missing repo enablerepo (yum)
  assert:
    that:
        - "yum_result is not success"
  when: ansible_pkg_mgr == 'yum'
- name: verify no change on fifth install with only missing repo enablerepo (dnf)
  assert:
    that:
        - "yum_result is success"
  when: ansible_pkg_mgr == 'dnf'

# INSTALL AGAIN WITH LATEST
- name: install {{ package1 }} again with state latest in check mode
  yum: name={{ package1 }} state=latest
  check_mode: true
  register: yum_result
- name: verify install {{ package1 }} again with state latest in check mode
  assert:
    that:
        - "not yum_result is changed"

- name: install {{ package1 }} again with state latest idempotence
  yum: name={{ package1 }} state=latest
  register: yum_result
- name: verify install {{ package1 }} again with state latest idempotence
  assert:
    that:
        - "not yum_result is changed"

# INSTALL WITH LATEST
- name: uninstall {{ package1 }}
  yum: name={{ package1 }} state=removed
  register: yum_result
- name: verify uninstall {{ package1 }}
  assert:
    that:
        - "yum_result is successful"

- name: copy yum.conf file in case it is missing
  copy:
    src: yum.conf
    dest: /etc/yum.conf
    force: False
  register: yum_conf_copy

- block:
  - name: install {{ package1 }} with state latest in check mode with config file param
    yum: name={{ package1 }} state=latest conf_file=/etc/yum.conf
    check_mode: true
    register: yum_result
  - name: verify install {{ package1 }} with state latest in check mode with config file param
    assert:
      that:
        - "yum_result is changed"

  always:
  - name: remove tmp yum.conf file if we created it
    file:
      path: /etc/yum.conf
      state: absent
    when: yum_conf_copy is changed

- name: install {{ package1 }} with state latest in check mode
  yum: name={{ package1 }} state=latest
  check_mode: true
  register: yum_result
- name: verify install {{ package1 }} with state latest in check mode
  assert:
    that:
        - "yum_result is changed"

- name: install {{ package1 }} with state latest
  yum: name={{ package1 }} state=latest
  register: yum_result
- name: verify install {{ package1 }} with state latest
  assert:
    that:
        - "yum_result is changed"

- name: install {{ package1 }} with state latest idempotence
  yum: name={{ package1 }} state=latest
  register: yum_result
- name: verify install {{ package1 }} with state latest idempotence
  assert:
    that:
        - "not yum_result is changed"

- name: install {{ package1 }} with state latest idempotence with config file param
  yum: name={{ package1 }} state=latest
  register: yum_result
- name: verify install {{ package1 }} with state latest idempotence with config file param
  assert:
    that:
        - "not yum_result is changed"


# Multiple packages
- name: uninstall {{ package1 }} and {{ package2 }}
  yum: name={{ package1 }},{{ package2 }} state=removed

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}
  ignore_errors: True
  register: rpm_package1_result

- name: check {{ package2 }} with rpm
  shell: rpm -q {{ package2 }}
  ignore_errors: True
  register: rpm_package2_result

- name: verify packages installed
  assert:
    that:
        - "rpm_package1_result is failed"
        - "rpm_package2_result is failed"

- name: install {{ package1 }} and {{ package2 }} as comma separated
  yum: name={{ package1 }},{{ package2 }} state=present
  register: yum_result

- name: verify packages installed
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}

- name: check {{ package2 }} with rpm
  shell: rpm -q {{ package2 }}

- name: uninstall {{ package1 }} and {{ package2 }}
  yum: name={{ package1 }},{{ package2 }} state=removed
  register: yum_result

- name: install {{ package1 }} and {{ package2 }} as list
  yum:
    name:
      - '{{ package1 }}'
      - '{{ package2 }}'
    state: present
  register: yum_result

- name: verify packages installed
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}

- name: check {{ package2 }} with rpm
  shell: rpm -q {{ package2 }}

- name: uninstall {{ package1 }} and {{ package2 }}
  yum: name={{ package1 }},{{ package2 }} state=removed
  register: yum_result

- name: install {{ package1 }} and {{ package2 }} as comma separated with spaces
  yum:
    name: "{{ package1 }}, {{ package2 }}"
    state: present
  register: yum_result

- name: verify packages installed
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }}

- name: check {{ package2 }} with rpm
  shell: rpm -q {{ package2 }}

- name: uninstall {{ package1 }} and {{ package2 }}
  yum: name={{ package1 }},{{ package2 }} state=removed

- name: install non-existent rpm
  yum:
    name: does-not-exist
  register: non_existent_rpm
  ignore_errors: True

- name: check non-existent rpm install failed
  assert:
    that:
    - non_existent_rpm is failed

# Install in installroot='/'
- name: install {{ package1 }}
  yum: name={{ package1 }} state=present installroot='/'
  register: yum_result

- name: verify installation of {{ package1 }}
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: check {{ package1 }} with rpm
  shell: rpm -q {{ package1 }} --root=/

- name: uninstall {{ package1 }}
  yum:
    name: '{{ package1 }}'
    installroot: '/'
    state: removed
  register: yum_result

# Seems like some yum versions won't download a package from local file repository, continue to use sos for this test.
# https://stackoverflow.com/questions/58295660/yum-downloadonly-ignores-packages-in-local-repo
- name: Test download_only
  yum:
    name: sos
    state: latest
    download_only: true
  register: yum_result

- name: verify download of sos (part 1 -- yum "install" succeeded)
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: uninstall sos (noop)
  yum:
    name: sos
    state: removed
  register: yum_result

- name: verify download of sos (part 2 -- nothing removed during uninstall)
  assert:
    that:
        - "yum_result is success"
        - "not yum_result is changed"

- name: uninstall sos for downloadonly/downloaddir test
  yum:
    name: sos
    state: absent

- name: Test download_only/download_dir
  yum:
    name: sos
    state: latest
    download_only: true
    download_dir: "/var/tmp/packages"
  register: yum_result

- name: verify yum output
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- command: "ls /var/tmp/packages"
  register: ls_out

- name: Verify specified download_dir was used
  assert:
    that:
      - "'sos' in ls_out.stdout"

- name: install group
  yum:
    name: "@Custom Group"
    state: present
  register: yum_result

- name: verify installation of the group
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: install the group again
  yum:
    name: "@Custom Group"
    state: present
  register: yum_result

- name: verify nothing changed
  assert:
    that:
        - "yum_result is success"
        - "not yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: install the group again but also with a package that is not yet installed
  yum:
    name:
      - "@Custom Group"
      - '{{ package2 }}'
    state: present
  register: yum_result

- name: verify {{ package3 }} is installed
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: try to install the group again, with --check to check 'changed'
  yum:
    name: "@Custom Group"
    state: present
  check_mode: yes
  register: yum_result

- name: verify nothing changed
  assert:
    that:
        - "not yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: try to install non existing group
  yum:
    name: "@non-existing-group"
    state: present
  register: yum_result
  ignore_errors: True

- name: verify installation of the non existing group failed
  assert:
    that:
        - "yum_result is failed"
        - "not yum_result is changed"
        - "yum_result is failed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: try to install non existing file
  yum:
    name: /tmp/non-existing-1.0.0.fc26.noarch.rpm
    state: present
  register: yum_result
  ignore_errors: yes

- name: verify installation failed
  assert:
    that:
        - "yum_result is failed"
        - "not yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"

- name: try to install from non existing url
  yum:
    name: https://ci-files.testing.ansible.com/test/integration/targets/yum/non-existing-1.0.0.fc26.noarch.rpm
    state: present
  register: yum_result
  ignore_errors: yes

- name: verify installation failed
  assert:
    that:
        - "yum_result is failed"
        - "not yum_result is changed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"

- name: use latest to install httpd
  yum:
    name: httpd
    state: latest
  register: yum_result

- name: verify httpd was installed
  assert:
    that:
      - "'changed' in yum_result"

- name: uninstall httpd
  yum:
    name: httpd
    state: removed

- name: update httpd only if it exists
  yum:
    name: httpd
    state: latest
    update_only: yes
  register: yum_result

- name: verify httpd not installed
  assert:
    that:
      - "not yum_result is changed"
      - "'Packages providing httpd not installed due to update_only specified' in yum_result.results"

- name: try to install uncompatible arch rpm on non-ppc64le, should fail
  yum:
    name: https://ci-files.testing.ansible.com/test/integration/targets/yum/banner-1.3.4-3.el7.ppc64le.rpm
    state: present
  register: yum_result
  ignore_errors: True
  when:
    - ansible_architecture not in ['ppc64le']

- name: verify that yum failed on non-ppc64le
  assert:
    that:
        - "not yum_result is changed"
        - "yum_result is failed"
  when:
    - ansible_architecture not in ['ppc64le']

- name: try to install uncompatible arch rpm on ppc64le, should fail
  yum:
    name: https://ci-files.testing.ansible.com/test/integration/targets/yum/tinyproxy-1.10.0-3.el7.x86_64.rpm
    state: present
  register: yum_result
  ignore_errors: True
  when:
    - ansible_architecture in ['ppc64le']

- name: verify that yum failed on ppc64le
  assert:
    that:
        - "not yum_result is changed"
        - "yum_result is failed"
  when:
    - ansible_architecture in ['ppc64le']

# setup for testing installing an RPM from url

- set_fact:
    pkg_name: noarchfake
    pkg_path: '{{ repodir }}/noarchfake-1.0-1.noarch.rpm'

- name: cleanup
  yum:
    name: "{{ pkg_name }}"
    state: absent

# setup end

- name: install a local noarch rpm from file
  yum:
    name: "{{ pkg_path }}"
    state: present
    disable_gpg_check: true
  register: yum_result

- name: verify installation
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"
        - "yum_result is not failed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: install the downloaded rpm again
  yum:
    name: "{{ pkg_path }}"
    state: present
  register: yum_result

- name: verify installation
  assert:
    that:
        - "yum_result is success"
        - "not yum_result is changed"
        - "yum_result is not failed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: clean up
  yum:
    name: "{{ pkg_name }}"
    state: absent

- name: install from url
  yum:
    name: "file://{{ pkg_path }}"
    state: present
    disable_gpg_check: true
  register: yum_result

- name: verify installation
  assert:
    that:
        - "yum_result is success"
        - "yum_result is changed"
        - "yum_result is not failed"

- name: verify yum module outputs
  assert:
    that:
        - "'changed' in yum_result"
        - "'msg' in yum_result"
        - "'results' in yum_result"

- name: Create a temp RPM file which does not contain nevra information
  file:
    name: "/tmp/non_existent_pkg.rpm"
    state: touch

- name: Try installing RPM file which does not contain nevra information
  yum:
    name: "/tmp/non_existent_pkg.rpm"
    state: present
  register: no_nevra_info_result
  ignore_errors: yes

- name: Verify RPM failed to install
  assert:
    that:
      - "'changed' in no_nevra_info_result"
      - "'msg' in no_nevra_info_result"

- name: Delete a temp RPM file
  file:
    name: "/tmp/non_existent_pkg.rpm"
    state: absent

- name: get yum version
  yum:
    list: yum
  register: yum_version

- name: set yum_version of installed version
  set_fact:
    yum_version: "{%- if item.yumstate == 'installed' -%}{{ item.version }}{%- else -%}{{ yum_version }}{%- endif -%}"
  with_items: "{{ yum_version.results }}"

- name: Ensure double uninstall of wildcard globs works
  block:
  - name: "Install lohit-*-fonts"
    yum:
      name: "lohit-*-fonts"
      state: present

  - name: "Remove lohit-*-fonts (1st time)"
    yum:
      name: "lohit-*-fonts"
      state: absent
    register: remove_lohit_fonts_1

  - name: "Verify lohit-*-fonts (1st time)"
    assert:
      that:
        - "remove_lohit_fonts_1 is changed"
        - "'msg' in remove_lohit_fonts_1"
        - "'results' in remove_lohit_fonts_1"

  - name: "Remove lohit-*-fonts (2nd time)"
    yum:
      name: "lohit-*-fonts"
      state: absent
    register: remove_lohit_fonts_2

  - name: "Verify lohit-*-fonts (2nd time)"
    assert:
      that:
        - "remove_lohit_fonts_2 is not changed"
        - "'msg' in remove_lohit_fonts_2"
        - "'results' in remove_lohit_fonts_2"
        - "'lohit-*-fonts is not installed' in remove_lohit_fonts_2['results']"

- block:
  - name: uninstall {{ package2 }}
    yum: name={{ package2 }} state=removed

  - name: check {{ package2 }} with rpm
    shell: rpm -q {{ package2 }}
    ignore_errors: True
    register: rpm_package2_result

  - name: verify {{ package2 }} is uninstalled
    assert:
      that:
        - "rpm_package2_result is failed"

  - name: exclude {{ package2 }} (yum backend)
    lineinfile:
      dest: /etc/yum.conf
      regexp: (^exclude=)(.)*
      line: "exclude={{ package2 }}*"
      state: present
    when: ansible_pkg_mgr == 'yum'

  - name: exclude {{ package2 }} (dnf backend)
    lineinfile:
      dest: /etc/dnf/dnf.conf
      regexp: (^excludepkgs=)(.)*
      line: "excludepkgs={{ package2 }}*"
      state: present
    when: ansible_pkg_mgr == 'dnf'

  # begin test case where disable_excludes is supported
  - name: Try install {{ package2 }} without disable_excludes
    yum: name={{ package2 }} state=latest
    register: yum_package2_result
    ignore_errors: True

  - name: verify {{ package2 }} did not install because it is in exclude list
    assert:
      that:
        - "yum_package2_result is failed"

  - name: install {{ package2 }} with disable_excludes
    yum: name={{ package2 }} state=latest disable_excludes=all
    register: yum_package2_result_using_excludes

  - name: verify {{ package2 }} did install using disable_excludes=all
    assert:
      that:
        - "yum_package2_result_using_excludes is success"
        - "yum_package2_result_using_excludes is changed"
        - "yum_package2_result_using_excludes is not failed"

  - name: remove exclude {{ package2 }} (cleanup yum.conf)
    lineinfile:
      dest: /etc/yum.conf
      regexp: (^exclude={{ package2 }}*)
      line: "exclude="
      state: present
    when: ansible_pkg_mgr == 'yum'

  - name: remove exclude {{ package2 }} (cleanup dnf.conf)
    lineinfile:
      dest: /etc/dnf/dnf.conf
      regexp: (^excludepkgs={{ package2 }}*)
      line: "excludepkgs="
      state: present
    when: ansible_pkg_mgr == 'dnf'

  # Fedora < 26 has a bug in dnf where package excludes in dnf.conf aren't
  # actually honored and those releases are EOL'd so we have no expectation they
  # will ever be fixed
  when: not ((ansible_distribution == "Fedora") and (ansible_distribution_major_version|int < 26))

- name: Check that packages with Provides are handled correctly in state=absent
  block:
    - name: Install test packages
      yum:
        name:
          - https://ci-files.testing.ansible.com/test/integration/targets/yum/test-package-that-provides-toaster-1.3.3.7-1.el7.noarch.rpm
          - https://ci-files.testing.ansible.com/test/integration/targets/yum/toaster-1.2.3.4-1.el7.noarch.rpm
        disable_gpg_check: true
      register: install

    - name: Remove toaster
      yum:
        name: toaster
        state: absent
      register: remove

    - name: rpm -qa
      command: rpm -qa
      register: rpmqa

    - assert:
        that:
          - install is successful
          - install is changed
          - remove is successful
          - remove is changed
          - "'toaster-1.2.3.4' not in rpmqa.stdout"
          - "'test-package-that-provides-toaster' in rpmqa.stdout"
  always:
    - name: Remove test packages
      yum:
        name:
          - test-package-that-provides-toaster
          - toaster
        state: absent

- yum:
    list: "{{ package1 }}"
  register: list_out

- name: check that both yum and dnf return envra
  assert:
    that:
      - '"envra" in list_out["results"][0]'

- name: check that dnf returns nevra for backwards compat
  assert:
    that:
      - '"nevra" in list_out["results"][0]'
  when: ansible_pkg_mgr == 'dnf'
