mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Pear - Add prompt parameter on pear module that allows to specify one or more prompts (#530)
* Add "prompt" parameter that allows to specify one or more prompts and optionnally their answer * Documentation backslash fixes as well as file structure * Add r prefix to documentation * Fixed documentation indentation * Fixed various trailing whitespaces and file structure * Doc description string fix, the tests thought it was an AnsibleMapping object * Added elements parameter to argument_spec definition. * Complete documentation. * Add bool instead of if else expression Co-Authored-By: tchernomax <maxime.deroucy@gmail.com> * Replace _item by a shorter expression as suggested Co-Authored-By: tchernomax <maxime.deroucy@gmail.com> * Commit suggestion Co-Authored-By: Felix Fontein <felix@fontein.de> * Commit documentation suggestion Co-Authored-By: Felix Fontein <felix@fontein.de> * Update changelogs/fragments/29253-pear_add_prompts_parameter.yml Co-Authored-By: Felix Fontein <felix@fontein.de> * Update plugins/modules/packaging/language/pear.py Co-Authored-By: tchernomax <maxime.deroucy@gmail.com> * Add case where "null" is specified in a list. Improved documentation as well * Too much caracter removed in documentation * We now always specify a prompt and a data parameter * minor documentation change * Update changelogs/fragments/29253-pear_add_prompts_parameter.yml Co-authored-by: Felix Fontein <felix@fontein.de> * pear: fix version_added Co-authored-by: Felix Fontein <felix@fontein.de> * pear: fix description Co-authored-by: Veltarn <dante161@gmail.com> Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
09e2b89d5b
commit
02a032aa45
2 changed files with 98 additions and 8 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- pear - added ``prompts`` parameter to allow users to specify expected prompt that could hang Ansible execution (https://github.com/ansible-collections/community.general/pull/530).
|
|
@ -31,11 +31,24 @@ options:
|
||||||
default: "present"
|
default: "present"
|
||||||
choices: ["present", "absent", "latest"]
|
choices: ["present", "absent", "latest"]
|
||||||
executable:
|
executable:
|
||||||
description:
|
description:
|
||||||
- Path to the pear executable
|
- Path to the pear executable.
|
||||||
|
prompts:
|
||||||
|
description:
|
||||||
|
- List of regular expressions that can be used to detect prompts during pear package installation to answer the expected question.
|
||||||
|
- Prompts will be processed in the same order as the packages list.
|
||||||
|
- You can optionnally specify an answer to any question in the list.
|
||||||
|
- If no answer is provided, the list item will only contain the regular expression.
|
||||||
|
- "To specify an answer, the item will be a dict with the regular expression as key and the answer as value C(my_regular_expression: 'an_answer')."
|
||||||
|
- You can provide a list containing items with or without answer.
|
||||||
|
- A prompt list can be shorter or longer than the packages list but will issue a warning.
|
||||||
|
- If you want to specify that a package will not need prompts in the middle of a list, C(null).
|
||||||
|
type: list
|
||||||
|
elements: raw
|
||||||
|
version_added: 0.2.0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = r'''
|
||||||
- name: Install pear package
|
- name: Install pear package
|
||||||
pear:
|
pear:
|
||||||
name: Net_URL2
|
name: Net_URL2
|
||||||
|
@ -46,6 +59,42 @@ EXAMPLES = '''
|
||||||
name: pecl/json_post
|
name: pecl/json_post
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
|
- name: Install pecl package with expected prompt
|
||||||
|
pear:
|
||||||
|
name: pecl/apcu
|
||||||
|
state: present
|
||||||
|
prompts:
|
||||||
|
- (.*)Enable internal debugging in APCu \[no\]
|
||||||
|
|
||||||
|
- name: Install pecl package with expected prompt and an answer
|
||||||
|
pear:
|
||||||
|
name: pecl/apcu
|
||||||
|
state: present
|
||||||
|
prompts:
|
||||||
|
- (.*)Enable internal debugging in APCu \[no\]: "yes"
|
||||||
|
|
||||||
|
- name: Install multiple pear/pecl packages at once with prompts.
|
||||||
|
Prompts will be processed on the same order as the packages order.
|
||||||
|
If there is more prompts than packages, packages without prompts will be installed without any prompt expected.
|
||||||
|
If there is more packages than prompts, additionnal prompts will be ignored.
|
||||||
|
pear:
|
||||||
|
name: pecl/gnupg, pecl/apcu
|
||||||
|
state: present
|
||||||
|
prompts:
|
||||||
|
- I am a test prompt because gnupg doesnt asks anything
|
||||||
|
- (.*)Enable internal debugging in APCu \[no\]: "yes"
|
||||||
|
|
||||||
|
- name: Install multiple pear/pecl packages at once skipping the first prompt.
|
||||||
|
Prompts will be processed on the same order as the packages order.
|
||||||
|
If there is more prompts than packages, packages without prompts will be installed without any prompt expected.
|
||||||
|
If there is more packages than prompts, additionnal prompts will be ignored.
|
||||||
|
pear:
|
||||||
|
name: pecl/gnupg, pecl/apcu
|
||||||
|
state: present
|
||||||
|
prompts:
|
||||||
|
- null
|
||||||
|
- (.*)Enable internal debugging in APCu \[no\]: "yes"
|
||||||
|
|
||||||
- name: Upgrade package
|
- name: Upgrade package
|
||||||
pear:
|
pear:
|
||||||
name: Net_URL2
|
name: Net_URL2
|
||||||
|
@ -145,9 +194,40 @@ def remove_packages(module, packages):
|
||||||
module.exit_json(changed=False, msg="package(s) already absent")
|
module.exit_json(changed=False, msg="package(s) already absent")
|
||||||
|
|
||||||
|
|
||||||
def install_packages(module, state, packages):
|
def install_packages(module, state, packages, prompts):
|
||||||
install_c = 0
|
install_c = 0
|
||||||
|
has_prompt = bool(prompts)
|
||||||
|
default_stdin = "\n"
|
||||||
|
|
||||||
|
if has_prompt:
|
||||||
|
nb_prompts = len(prompts)
|
||||||
|
nb_packages = len(packages)
|
||||||
|
|
||||||
|
if nb_prompts > 0 and (nb_prompts != nb_packages):
|
||||||
|
if nb_prompts > nb_packages:
|
||||||
|
diff = nb_prompts - nb_packages
|
||||||
|
msg = "%s packages to install but %s prompts to expect. %s prompts will be ignored" % (to_text(nb_packages), to_text(nb_prompts), to_text(diff))
|
||||||
|
else:
|
||||||
|
diff = nb_packages - nb_prompts
|
||||||
|
msg = "%s packages to install but only %s prompts to expect. %s packages won't be expected to have a prompt" \
|
||||||
|
% (to_text(nb_packages), to_text(nb_prompts), to_text(diff))
|
||||||
|
module.warn(msg)
|
||||||
|
|
||||||
|
# Preparing prompts answer according to item type
|
||||||
|
tmp_prompts = []
|
||||||
|
for _item in prompts:
|
||||||
|
# If the current item is a dict then we expect it's key to be the prompt regex and it's value to be the answer
|
||||||
|
# We also expect here that the dict only has ONE key and the first key will be taken
|
||||||
|
if isinstance(_item, dict):
|
||||||
|
key = list(_item.keys())[0]
|
||||||
|
answer = _item[key] + "\n"
|
||||||
|
|
||||||
|
tmp_prompts.append((key, answer))
|
||||||
|
elif not _item:
|
||||||
|
tmp_prompts.append((None, default_stdin))
|
||||||
|
else:
|
||||||
|
tmp_prompts.append((_item, default_stdin))
|
||||||
|
prompts = tmp_prompts
|
||||||
for i, package in enumerate(packages):
|
for i, package in enumerate(packages):
|
||||||
# if the package is installed and state == present
|
# if the package is installed and state == present
|
||||||
# or state == latest and is up-to-date then skip
|
# or state == latest and is up-to-date then skip
|
||||||
|
@ -161,9 +241,15 @@ def install_packages(module, state, packages):
|
||||||
if state == 'latest':
|
if state == 'latest':
|
||||||
command = 'upgrade'
|
command = 'upgrade'
|
||||||
|
|
||||||
cmd = "%s %s %s" % (_get_pear_path(module), command, package)
|
if has_prompt and i < len(prompts):
|
||||||
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
|
prompt_regex = prompts[i][0]
|
||||||
|
data = prompts[i][1]
|
||||||
|
else:
|
||||||
|
prompt_regex = None
|
||||||
|
data = default_stdin
|
||||||
|
|
||||||
|
cmd = "%s %s %s" % (_get_pear_path(module), command, package)
|
||||||
|
rc, stdout, stderr = module.run_command(cmd, check_rc=False, prompt_regex=prompt_regex, data=data, binary_data=True)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
module.fail_json(msg="failed to install %s: %s" % (package, to_text(stdout + stderr)))
|
module.fail_json(msg="failed to install %s: %s" % (package, to_text(stdout + stderr)))
|
||||||
|
|
||||||
|
@ -197,7 +283,9 @@ def main():
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
name=dict(aliases=['pkg'], required=True),
|
name=dict(aliases=['pkg'], required=True),
|
||||||
state=dict(default='present', choices=['present', 'installed', "latest", 'absent', 'removed']),
|
state=dict(default='present', choices=['present', 'installed', "latest", 'absent', 'removed']),
|
||||||
executable=dict(default=None, required=False, type='path')),
|
executable=dict(default=None, required=False, type='path'),
|
||||||
|
prompts=dict(default=None, required=False, type='list', elements='raw'),
|
||||||
|
),
|
||||||
supports_check_mode=True)
|
supports_check_mode=True)
|
||||||
|
|
||||||
p = module.params
|
p = module.params
|
||||||
|
@ -219,7 +307,7 @@ def main():
|
||||||
check_packages(module, pkgs, p['state'])
|
check_packages(module, pkgs, p['state'])
|
||||||
|
|
||||||
if p['state'] in ['present', 'latest']:
|
if p['state'] in ['present', 'latest']:
|
||||||
install_packages(module, p['state'], pkgs)
|
install_packages(module, p['state'], pkgs, p["prompts"])
|
||||||
elif p['state'] == 'absent':
|
elif p['state'] == 'absent':
|
||||||
remove_packages(module, pkgs)
|
remove_packages(module, pkgs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue