Reputation: 33
I have an ansible playbook developed using Chocolatey to upgrade a set of packages. However, I want the playbook to only upgrade a package if it is installed and skip if the package is not present. However, what the playbook is doing is upgrading present packages but installing the packages that are not present. I know from the playbook that it is doing exactly what it is supposed to do because of the state being set to latest. What I want to know is how to modify the playbook to only upgrade present packages (possibly using a when: statement) but I cannot seem to find anything out there to help with this. Thanks in advance.
Below is the ansible playbook. And yes, I know I could include the packages in a loop rather than running them one at a time but I found that is not as verbose as I would like.
---
- hosts: all
tasks:
- name: Update putty on Windows machines
win_chocolatey:
name: putty
state: latest
- name: Update WinSCP on Windows machines
win_chocolatey:
name: winscp
state: latest
- name: Update Notepad++ on Windows machines
win_chocolatey:
name: notepadplusplus
state: latest
- name: Update SQL Server Management Studio on Windows machines
win_chocolatey:
name: sql-server-management-studio
state: latest
- name: Update Firefox on Windows machines
win_chocolatey:
name: firefox
state: latest
- name: Update Google Chrome on Windows machines
win_chocolatey:
name: googlechrome
state: latest
- name: Update Brave Browser on Windows machines
win_chocolatey:
name: brave
state: latest
- name: Update 7zip on Windows machines
win_chocolatey:
name: 7zip
state: latest
- name: Update TreeSize Free on Windows machines
win_chocolatey:
name: treesizefree
state: latest
- name: Update Wireshark on Windows machines
win_chocolatey:
name: wireshark
state: latest
- name: Update PowerBI data gateway on Windows machines
win_chocolatey:
name: powerbigateway
state: latest
- name: Update RVTools on Windows machines
win_chocolatey:
name: rvtools
state: latest
Upvotes: 3
Views: 1320
Reputation: 1
This will search for outdated packages and upgrade them without an exact name or number:
tasks:
- name: gathering choco facts
win_chocolatey_facts:
filter:
- 'outdated'
- 'packages'
register: choco_name
- name: count outdated packages
debug:
msg: "{{ ansible_chocolatey.outdated|length }}"
- name: filter outdated packagename
debug:
msg:
- "{{ choco_name.ansible_facts.ansible_chocolatey.outdated[item].package }}"
loop: "{{ range(1, ansible_chocolatey.outdated|length +1, 1) }}"
loop_control:
index_var: item
- name: update outdated Packages
win_chocolatey:
name:
- "{{ choco_name.ansible_facts.ansible_chocolatey.outdated[item].package }}"
state: upgrade
loop: "{{ range(1, ansible_chocolatey.outdated|length +1, 1) }}"
loop_control:
index_var: item
Upvotes: 0
Reputation: 19021
In addition to the answer provided by @Windos, you may want to look at the skipPackageUpgradesWhenNotInstalled
configuration option. From the docs page:
skipPackageUpgradesWhenNotInstalled - Skip Packages Not Installed During Upgrade - if a package is not installed, do not install it during the upgrade process.
This feature is disabled by default, but you should be able to enable it as part of your playbook. From the documentation for the collection:
- name: Enable Chocolatey Feature to skip not installed packages
win_chocolatey_feature:
name: skipPackageUpgradesWhenNotInstalled
state: enabled
Off the top of my head, I am not sure whether the exit code from Chocolatey changes if it actually skips a package since it wasn't installed, so this might be something that you want to test to ensure it doesn't impact on anything else that you are trying to do with the playbook.
Upvotes: 2
Reputation: 1956
What you need to do is first check what packages are installed, you can do this with the win_chocolatey_facts
module.
If you just want to update all installed packages, then you can loop through what that module returns and do the update:
---
- hosts: all
tasks:
- name: Gather facts from Chocolatey CLI
win_chocolatey_facts:
- name: Upgrade installed packages
win_chocolatey:
name: '{{ item.package }}'
state: latest
failed_when: false # Setting this means if one package fails, the loop will continue. You can remove it if you don't want that behaviour.
loop: '{{ ansible_chocolatey.packages }}' # This variable comes from the facts task above automatically.
...
If you do only want to care about the intersection of packages between your list and what's on the machine, then I'd suggest storing that list of packages in a variable and checking against it in your loop.
---
- hosts: all
vars:
chocolatey_packages_to_upgrade:
- putty
- winscp
- notepadplusplus
- sql-server-management-studio
- firefox
- googlechrome
- brave
- 7zip
- treesizefree
- wireshark
- powerbigateway
tasks:
- name: Gather facts from Chocolatey CLI
win_chocolatey_facts:
- name: Upgrade installed packages
win_chocolatey:
name: '{{ item.package }}'
state: latest
when: item.package in chocolatey_packages_to_upgrade # Only process this package if the package is in the predefined list
failed_when: false # Setting this means if one package fails, the loop will continue. You can remove it if you don't want that behaviour.
loop: '{{ ansible_chocolatey.packages }}' # This variable comes from the facts task above automatically.
...
You can always reverse this loop, that is you can loop on your desired packages and only upgrade if they were found in the automatic variable from the facts module.
Also, if you'd prefer not to use a loop at all, you can still do your individual tasks like this:
- name: Update putty on Windows machines
win_chocolatey:
name: putty
state: latest
when: '"putty" in ansible_chocolatey.packages'
Upvotes: 3