diff --git a/changelogs/fragments/8431-galaxy-upgrade.yml b/changelogs/fragments/8431-galaxy-upgrade.yml new file mode 100644 index 0000000000..9be9ca93c8 --- /dev/null +++ b/changelogs/fragments/8431-galaxy-upgrade.yml @@ -0,0 +1,2 @@ +minor_changes: + - ansible_galaxy_install - add upgrade feature (https://github.com/ansible-collections/community.general/pull/8431, https://github.com/ansible-collections/community.general/issues/8351). diff --git a/plugins/modules/ansible_galaxy_install.py b/plugins/modules/ansible_galaxy_install.py index d382ed93a9..b0f3aeb5da 100644 --- a/plugins/modules/ansible_galaxy_install.py +++ b/plugins/modules/ansible_galaxy_install.py @@ -32,6 +32,19 @@ attributes: diff_mode: support: none options: + state: + description: + - > + If O(state=present) then the collection or role will be installed. + Note that the collections and roles are not updated with this option. + - > + Currently the O(state=latest) is ignored unless O(type=collection), and it will + ensure the collection is installed and updated to the latest available version. + - Please note that O(force=true) can be used to perform upgrade regardless of O(type). + type: str + choices: [ present, latest ] + default: present + version_added: 9.1.0 type: description: - The type of installation performed by C(ansible-galaxy). @@ -69,7 +82,8 @@ options: default: false force: description: - - Force overwriting an existing role or collection. + - Force overwriting existing roles and/or collections. + - It can be used for upgrading, but the module output will always report C(changed=true). - Using O(force=true) is mandatory when downgrading. type: bool default: false @@ -188,6 +202,7 @@ class AnsibleGalaxyInstall(ModuleHelper): output_params = ('type', 'name', 'dest', 'requirements_file', 'force', 'no_deps') module = dict( argument_spec=dict( + state=dict(type='str', choices=['present', 'latest'], default='present'), type=dict(type='str', choices=('collection', 'role', 'both'), required=True), name=dict(type='str'), requirements_file=dict(type='path'), @@ -206,6 +221,7 @@ class AnsibleGalaxyInstall(ModuleHelper): command_args_formats = dict( type=cmd_runner_fmt.as_func(lambda v: [] if v == 'both' else [v]), galaxy_cmd=cmd_runner_fmt.as_list(), + upgrade=cmd_runner_fmt.as_bool("--upgrade"), requirements_file=cmd_runner_fmt.as_opt_val('-r'), dest=cmd_runner_fmt.as_opt_val('-p'), force=cmd_runner_fmt.as_bool("--force"), @@ -244,9 +260,7 @@ class AnsibleGalaxyInstall(ModuleHelper): def __init_module__(self): self.runner, self.ansible_version = self._get_ansible_galaxy_version() if self.ansible_version < (2, 11): - self.module.fail_json( - msg="Support for Ansible 2.9 and ansible-base 2.10 has been removed." - ) + self.module.fail_json(msg="Support for Ansible 2.9 and ansible-base 2.10 has been removed.") self.vars.set("new_collections", {}, change=True) self.vars.set("new_roles", {}, change=True) if self.vars.type != "collection": @@ -299,8 +313,9 @@ class AnsibleGalaxyInstall(ModuleHelper): elif match.group("role"): self.vars.new_roles[match.group("role")] = match.group("rversion") - with self.runner("type galaxy_cmd force no_deps dest requirements_file name", output_process=process) as ctx: - ctx.run(galaxy_cmd="install") + upgrade = (self.vars.type == "collection" and self.vars.state == "latest") + with self.runner("type galaxy_cmd upgrade force no_deps dest requirements_file name", output_process=process) as ctx: + ctx.run(galaxy_cmd="install", upgrade=upgrade) if self.verbosity > 2: self.vars.set("run_info", ctx.run_info) diff --git a/tests/integration/targets/ansible_galaxy_install/tasks/main.yml b/tests/integration/targets/ansible_galaxy_install/tasks/main.yml index 1ecd9980d4..5c4af6d167 100644 --- a/tests/integration/targets/ansible_galaxy_install/tasks/main.yml +++ b/tests/integration/targets/ansible_galaxy_install/tasks/main.yml @@ -4,10 +4,16 @@ # SPDX-License-Identifier: GPL-3.0-or-later ################################################### +- name: Make directory install_c + ansible.builtin.file: + path: "{{ remote_tmp_dir }}/install_c" + state: directory + - name: Install collection netbox.netbox community.general.ansible_galaxy_install: type: collection name: netbox.netbox + dest: "{{ remote_tmp_dir }}/install_c" register: install_c0 - name: Assert collection netbox.netbox was installed @@ -20,6 +26,7 @@ community.general.ansible_galaxy_install: type: collection name: netbox.netbox + dest: "{{ remote_tmp_dir }}/install_c" register: install_c1 - name: Assert collection was not installed @@ -28,10 +35,16 @@ - install_c1 is not changed ################################################### +- name: Make directory install_r + ansible.builtin.file: + path: "{{ remote_tmp_dir }}/install_r" + state: directory + - name: Install role ansistrano.deploy community.general.ansible_galaxy_install: type: role name: ansistrano.deploy + dest: "{{ remote_tmp_dir }}/install_r" register: install_r0 - name: Assert collection ansistrano.deploy was installed @@ -44,6 +57,7 @@ community.general.ansible_galaxy_install: type: role name: ansistrano.deploy + dest: "{{ remote_tmp_dir }}/install_r" register: install_r1 - name: Assert role was not installed @@ -86,3 +100,44 @@ assert: that: - install_rq1 is not changed + +################################################### +- name: Make directory upgrade_c + ansible.builtin.file: + path: "{{ remote_tmp_dir }}/upgrade_c" + state: directory + +- name: Install collection netbox.netbox 3.17.0 + community.general.ansible_galaxy_install: + type: collection + name: netbox.netbox:3.17.0 + dest: "{{ remote_tmp_dir }}/upgrade_c" + register: upgrade_c0 + +- name: Assert collection netbox.netbox was installed + assert: + that: + - upgrade_c0 is changed + - '"netbox.netbox" in upgrade_c0.new_collections' + +- name: Upgrade collection netbox.netbox + community.general.ansible_galaxy_install: + state: latest + type: collection + name: netbox.netbox + dest: "{{ remote_tmp_dir }}/upgrade_c" + register: upgrade_c1 + +- name: Upgrade collection netbox.netbox (again) + community.general.ansible_galaxy_install: + state: latest + type: collection + name: netbox.netbox + dest: "{{ remote_tmp_dir }}/upgrade_c" + register: upgrade_c2 + +- name: Assert collection was not installed + assert: + that: + - upgrade_c1 is changed + - upgrade_c2 is not changed