-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'state' parameter for alternatives #4557
Changes from all commits
7ef07f8
f8a9531
8a19fcf
f393a12
272275c
4257962
f3952f9
9ffd3b2
45fe436
6ac7eb1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
minor_changes: | ||
- alternatives - add ``state`` parameter, which provides control over whether the alternative should be set as the active selection for its alternatives group (https://github.com/ansible-collections/community.general/issues/4543, https://github.com/ansible-collections/community.general/pull/4557). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,16 @@ | |
- The priority of the alternative. | ||
type: int | ||
default: 50 | ||
state: | ||
description: | ||
- C(present) - install the alternative (if not already installed), but do | ||
not set it as the currently selected alternative for the group. | ||
- C(selected) - install the alternative (if not already installed), and | ||
set it as the currently selected alternative for the group. | ||
choices: [ present, selected ] | ||
default: selected | ||
type: str | ||
version_added: 4.8.0 | ||
requirements: [ update-alternatives ] | ||
''' | ||
|
||
|
@@ -61,6 +71,13 @@ | |
name: java | ||
path: /usr/lib/jvm/java-7-openjdk-i386/jre/bin/java | ||
priority: -10 | ||
|
||
- name: Install Python 3.5 but do not select it | ||
community.general.alternatives: | ||
name: python | ||
path: /usr/bin/python3.5 | ||
link: /usr/bin/python | ||
state: present | ||
''' | ||
|
||
import os | ||
|
@@ -70,6 +87,15 @@ | |
from ansible.module_utils.basic import AnsibleModule | ||
|
||
|
||
class AlternativeState: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A bit of a nit-picking but I think both terms in the name should be plural:
Also I think we might want to consider prefixing that class name with a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are many arguments for and against using a plural vs. a singular name for an enumeration. Java and C# seem to prefer singular names (https://stackoverflow.com/a/15756009). I guess in the end it's a matter of taste.
I wouldn't consider modules (as opposed to module_utils etc.) a public API. The guidelines only talk about public/private module and plugin utils. Maybe we should discuss this in community-topics... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough. I reckon this is not a show stopper. |
||
PRESENT = "present" | ||
SELECTED = "selected" | ||
|
||
@classmethod | ||
def to_list(cls): | ||
return [cls.PRESENT, cls.SELECTED] | ||
|
||
|
||
def main(): | ||
|
||
module = AnsibleModule( | ||
|
@@ -78,6 +104,11 @@ def main(): | |
path=dict(type='path', required=True), | ||
link=dict(type='path'), | ||
priority=dict(type='int', default=50), | ||
state=dict( | ||
type='str', | ||
choices=AlternativeState.to_list(), | ||
default=AlternativeState.SELECTED, | ||
), | ||
), | ||
supports_check_mode=True, | ||
) | ||
|
@@ -87,6 +118,7 @@ def main(): | |
path = params['path'] | ||
link = params['link'] | ||
priority = params['priority'] | ||
state = params['state'] | ||
|
||
UPDATE_ALTERNATIVES = module.get_bin_path('update-alternatives', True) | ||
|
||
|
@@ -126,9 +158,20 @@ def main(): | |
link = line.split()[1] | ||
break | ||
|
||
changed = False | ||
if current_path != path: | ||
|
||
# Check mode: expect a change if this alternative is not already | ||
# installed, or if it is to be set as the current selection. | ||
if module.check_mode: | ||
module.exit_json(changed=True, current_path=current_path) | ||
module.exit_json( | ||
changed=( | ||
path not in all_alternatives or | ||
state == AlternativeState.SELECTED | ||
), | ||
current_path=current_path, | ||
) | ||
|
||
try: | ||
# install the requested path if necessary | ||
if path not in all_alternatives: | ||
|
@@ -141,18 +184,34 @@ def main(): | |
[UPDATE_ALTERNATIVES, '--install', link, name, path, str(priority)], | ||
check_rc=True | ||
) | ||
changed = True | ||
|
||
# select the requested path | ||
# set the current selection to this path (if requested) | ||
if state == AlternativeState.SELECTED: | ||
module.run_command( | ||
[UPDATE_ALTERNATIVES, '--set', name, path], | ||
check_rc=True | ||
) | ||
changed = True | ||
|
||
except subprocess.CalledProcessError as cpe: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this not covered by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, actually There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That can also be done later. |
||
module.fail_json(msg=str(dir(cpe))) | ||
elif current_path == path and state == AlternativeState.PRESENT: | ||
# Case where alternative is currently selected, but state is set | ||
# to 'present'. In this case, we set to auto mode. | ||
if module.check_mode: | ||
module.exit_json(changed=True, current_path=current_path) | ||
|
||
changed = True | ||
try: | ||
module.run_command( | ||
[UPDATE_ALTERNATIVES, '--set', name, path], | ||
check_rc=True | ||
[UPDATE_ALTERNATIVES, '--auto', name], | ||
check_rc=True, | ||
) | ||
|
||
module.exit_json(changed=True) | ||
except subprocess.CalledProcessError as cpe: | ||
module.fail_json(msg=str(dir(cpe))) | ||
else: | ||
module.exit_json(changed=False) | ||
|
||
module.exit_json(changed=changed) | ||
|
||
|
||
if __name__ == '__main__': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Add a few dummy alternatives with state = present and make sure that the | ||
# group is in 'auto' mode and the highest priority alternative is selected. | ||
- name: Add some dummy alternatives with state = present | ||
alternatives: | ||
name: dummy | ||
path: "/usr/bin/dummy{{ item.n }}" | ||
link: /usr/bin/dummy | ||
priority: "{{ item.priority }}" | ||
state: present | ||
loop: | ||
- { n: 1, priority: 50 } | ||
- { n: 2, priority: 70 } | ||
- { n: 3, priority: 25 } | ||
|
||
- name: Ensure that the link group is in auto mode | ||
felixfontein marked this conversation as resolved.
Show resolved
Hide resolved
|
||
shell: 'head -n1 {{ alternatives_dir }}/dummy | grep "^auto$"' | ||
|
||
# Execute current selected 'dummy' and ensure it's the alternative we expect | ||
- name: Execute the current dummy command | ||
shell: dummy | ||
register: cmd | ||
|
||
- name: Ensure that the expected command was executed | ||
assert: | ||
that: | ||
- cmd.stdout == "dummy2" | ||
|
||
# Add another alternative with state = 'selected' and make sure that | ||
# this change results in the group being set to manual mode, and the | ||
# new alternative being the selected one. | ||
- name: Add another dummy alternative with state = selected | ||
alternatives: | ||
name: dummy | ||
path: /usr/bin/dummy4 | ||
link: /usr/bin/dummy | ||
priority: 10 | ||
state: selected | ||
|
||
- name: Ensure that the link group is in manual mode | ||
shell: 'head -n1 {{ alternatives_dir }}/dummy | grep "^manual$"' | ||
|
||
- name: Execute the current dummy command | ||
shell: dummy | ||
register: cmd | ||
|
||
- name: Ensure that the expected command was executed | ||
assert: | ||
that: | ||
- cmd.stdout == "dummy4" | ||
|
||
# Set the currently selected alternative to state = 'present' (was previously | ||
# selected), and ensure that this results in the group being set to 'auto' | ||
# mode, and the highest priority alternative is selected. | ||
- name: Set current selected dummy to state = present | ||
alternatives: | ||
name: dummy | ||
path: /usr/bin/dummy4 | ||
link: /usr/bin/dummy | ||
state: present | ||
|
||
- name: Ensure that the link group is in auto mode | ||
shell: 'head -n1 {{ alternatives_dir }}/dummy | grep "^auto$"' | ||
|
||
- name: Execute the current dummy command | ||
shell: dummy | ||
register: cmd | ||
|
||
- name: Ensure that the expected command was executed | ||
assert: | ||
that: | ||
- cmd.stdout == "dummy2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe to clarify: