diff --git a/CHANGELOG.md b/CHANGELOG.md index a4361a998..0da437282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* **role:alternatives**: Support managing `subcommands` (slaves/followers) and the Red Hat-only `family` grouping. The role now also ensures the alternatives tooling is installed (`chkconfig` on RHEL 8, `alternatives` on RHEL 9/10; bundled with `dpkg` on Debian/Ubuntu), and can be included without variables as a no-op. * **role:mariadb_server**: Add `mariadb_server__cnf_innodb_snapshot_isolation` variable (MariaDB 10.6+), defaulting to `'ON'`. ### Security diff --git a/roles/alternatives/README.md b/roles/alternatives/README.md index 2a7e132b3..f4015defd 100644 --- a/roles/alternatives/README.md +++ b/roles/alternatives/README.md @@ -12,31 +12,43 @@ Hints: *Available since LFOps `3.0.0`.* +## How the Role Behaves + +* The role ensures the alternatives tooling is installed: the `chkconfig` package on RHEL 8, the `alternatives` package on RHEL 9 and 10. On Debian and Ubuntu, `update-alternatives` ships with `dpkg`, so nothing is installed there. +* On Red Hat-family hosts `link` is mandatory for each entry. On Debian-based hosts it is only required when the alternative `name` is unknown to the system. +* `family` is only available on Red Hat-family hosts (community.general 10.1.0+); `subcommands` requires community.general 5.1.0+. Both are passed through only when set, so they do not affect entries or platforms that do not use them. + + ## Tags `alternatives` -* Manages alternative programs for common commands. +* Installs the alternatives tooling and manages alternative programs for common commands. * Triggers: none. -## Mandatory Role Variables +## Optional Role Variables `alternatives__alternatives` -* List of alternatives to remove or to deploy. +* List of alternatives to remove or to deploy. With the default empty list, the role is a no-op. * Type: List of dictionaries. * Default: `[]` * Subkeys: - * `link`: + * `name`: - * The path to the symbolic link that should point to the real executable. This option is always required on RHEL-based distributions. On Debian-based distributions this option is required when the alternative `name` is unknown to the system. + * Mandatory. The generic name of the link. * Type: String. - * `name`: + * `family`: - * Mandatory. The generic name of the link. + * Optional. Groups similar alternatives. Red Hat-family only. + * Type: String. + + * `link`: + + * The path to the symbolic link that should point to the real executable. This option is always required on RHEL-based distributions. On Debian-based distributions this option is required when the alternative `name` is unknown to the system. * Type: String. * `path`: @@ -46,7 +58,7 @@ Hints: * `priority`: - * Optional. The priority of the alternative. If no priority is given for creation `50` is used as a fallback. + * Optional. The priority of the alternative. If no priority is given, the `alternatives` tool uses `50` as a fallback on creation. * Type: Number. * `state`: @@ -55,20 +67,31 @@ Hints: * Type: String. * Default: `'selected'` + * `subcommands`: + + * Optional. Subcommands (also called slaves or followers) that are switched together with this alternative. Each entry needs `name`, `link`, and `path`. + * Type: List of dictionaries. + Example: ```yaml alternatives__alternatives: - - link: '/usr/bin/python3' - name: 'python3' - path: '/usr/bin/python3.9' - priority: '100' # install python3.9 with higher priority - state: 'auto' - - link: '/usr/bin/python3' - name: 'python3' + # set the default python3, also switching its subcommands (slaves) + - name: 'python3' + link: '/usr/bin/python3' path: '/usr/bin/python3.12' - priority: '10' + priority: 100 state: 'auto' -# => results in python3.9 + subcommands: + - name: 'python3-config' + link: '/usr/bin/python3-config' + path: '/usr/bin/python3.12-config' + # Red Hat-family only: select an alternative by family + - name: 'java' + family: 'java-11-openjdk.x86_64' + # remove an alternative + - name: 'editor' + path: '/usr/bin/vim' + state: 'absent' ``` diff --git a/roles/alternatives/defaults/main.yml b/roles/alternatives/defaults/main.yml new file mode 100644 index 000000000..199ab387f --- /dev/null +++ b/roles/alternatives/defaults/main.yml @@ -0,0 +1 @@ +alternatives__alternatives: [] diff --git a/roles/alternatives/meta/argument_specs.yml b/roles/alternatives/meta/argument_specs.yml index 4a2d84806..8700dd97b 100644 --- a/roles/alternatives/meta/argument_specs.yml +++ b/roles/alternatives/meta/argument_specs.yml @@ -5,11 +5,19 @@ argument_specs: alternatives__alternatives: type: 'list' elements: 'dict' - required: true + required: false + default: [] description: >- List of `update-alternatives` entries to manage. options: + family: + type: 'str' + required: false + description: >- + Groups similar alternatives. Red Hat-family only + (community.general 10.1.0+). + link: type: 'str' required: false @@ -33,8 +41,8 @@ argument_specs: type: 'int' required: false description: >- - Priority weight for `auto` mode (default fallback for - creation: 50). + Priority weight for `auto` mode. If unset, the module + falls back to 50 on creation. state: type: 'str' @@ -47,3 +55,27 @@ argument_specs: - 'selected' description: >- `selected` (default), `present`, `auto`, or `absent`. + + subcommands: + type: 'list' + elements: 'dict' + required: false + description: >- + Subcommands (also called slaves or followers) switched + together with this alternative (community.general 5.1.0+). + options: + + link: + type: 'str' + required: true + description: 'Path to the subcommand symlink.' + + name: + type: 'str' + required: true + description: 'The generic name of the subcommand.' + + path: + type: 'str' + required: true + description: 'Path to the real subcommand executable.' diff --git a/roles/alternatives/tasks/main.yml b/roles/alternatives/tasks/main.yml index 09331ace7..e5cd6c786 100644 --- a/roles/alternatives/tasks/main.yml +++ b/roles/alternatives/tasks/main.yml @@ -1,5 +1,25 @@ - block: + - name: 'Set platform/version specific variables' + ansible.builtin.import_role: + name: 'shared' + tasks_from: 'platform-variables.yml' + + tags: + - 'always' + + +- block: + + # Debian/Ubuntu ship update-alternatives with dpkg, so __alternatives__packages + # is empty there and this task is skipped. + - name: 'Install the alternatives tooling' + ansible.builtin.package: + name: '{{ __alternatives__packages }}' + state: 'present' + when: + - '__alternatives__packages | length > 0' + - name: 'Debug' ansible.builtin.debug: msg: @@ -9,11 +29,13 @@ # alternatives --install - name: 'Manages alternative programs for common commands' community.general.alternatives: - link: '{{ item["link"] }}' name: '{{ item["name"] }}' - path: '{{ item["path"] }}' - priority: '{{ item["priority"] | d(50) }}' + link: '{{ item["link"] | default(omit) }}' + path: '{{ item["path"] | default(omit) }}' + priority: '{{ item["priority"] | default(omit) }}' state: '{{ item["state"] | d("selected") }}' + subcommands: '{{ item["subcommands"] | default(omit) }}' + family: '{{ item["family"] | default(omit) }}' loop: '{{ alternatives__alternatives }}' tags: diff --git a/roles/alternatives/vars/RedHat10.yml b/roles/alternatives/vars/RedHat10.yml new file mode 100644 index 000000000..8a9bd27d0 --- /dev/null +++ b/roles/alternatives/vars/RedHat10.yml @@ -0,0 +1,3 @@ +# Since RHEL 9 the `alternatives` command has its own package. +__alternatives__packages: + - 'alternatives' diff --git a/roles/alternatives/vars/RedHat8.yml b/roles/alternatives/vars/RedHat8.yml new file mode 100644 index 000000000..02373be25 --- /dev/null +++ b/roles/alternatives/vars/RedHat8.yml @@ -0,0 +1,3 @@ +# On RHEL 8 the `alternatives` command is provided by the chkconfig package. +__alternatives__packages: + - 'chkconfig' diff --git a/roles/alternatives/vars/RedHat9.yml b/roles/alternatives/vars/RedHat9.yml new file mode 100644 index 000000000..8a9bd27d0 --- /dev/null +++ b/roles/alternatives/vars/RedHat9.yml @@ -0,0 +1,3 @@ +# Since RHEL 9 the `alternatives` command has its own package. +__alternatives__packages: + - 'alternatives' diff --git a/roles/alternatives/vars/main.yml b/roles/alternatives/vars/main.yml new file mode 100644 index 000000000..b36c84c80 --- /dev/null +++ b/roles/alternatives/vars/main.yml @@ -0,0 +1,3 @@ +# Base default. The alternatives tooling ships with dpkg on Debian/Ubuntu, so +# nothing needs to be installed there. Red Hat-family overrides this per version. +__alternatives__packages: []