Zypper repo autoimport keys (#2132)
* zypper_repository add auto_import_keys options * also give more output on failure (rc, stdout, stderr) * be more specific in the doc for auto_import_keys * add runrefresh option to zypper_repository * this comes out of ansible/ansible-modules-extras#2411, where AnderEnder adds refresh to the zypper module * adds a way to force zypper to refresh a repository * can be used to refresh independently of auto_import_keys * add option to run name=* runrefresh=yes * name runrefresh to not break existing use to refresh (now alias to autorefresh) * add version_added flag to autorefresh * remove wrong version_added comment
This commit is contained in:
parent
961c076e72
commit
6c9c4e7482
1 changed files with 83 additions and 34 deletions
|
@ -59,12 +59,13 @@ options:
|
||||||
required: false
|
required: false
|
||||||
default: "no"
|
default: "no"
|
||||||
choices: [ "yes", "no" ]
|
choices: [ "yes", "no" ]
|
||||||
refresh:
|
autorefresh:
|
||||||
description:
|
description:
|
||||||
- Enable autorefresh of the repository.
|
- Enable autorefresh of the repository.
|
||||||
required: false
|
required: false
|
||||||
default: "yes"
|
default: "yes"
|
||||||
choices: [ "yes", "no" ]
|
choices: [ "yes", "no" ]
|
||||||
|
aliases: [ "refresh" ]
|
||||||
priority:
|
priority:
|
||||||
description:
|
description:
|
||||||
- Set priority of repository. Packages will always be installed
|
- Set priority of repository. Packages will always be installed
|
||||||
|
@ -80,6 +81,26 @@ options:
|
||||||
default: "no"
|
default: "no"
|
||||||
choices: [ "yes", "no" ]
|
choices: [ "yes", "no" ]
|
||||||
version_added: "2.1"
|
version_added: "2.1"
|
||||||
|
auto_import_keys:
|
||||||
|
description:
|
||||||
|
- Automatically import the gpg signing key of the new or changed repository.
|
||||||
|
- Has an effect only if state is I(present). Has no effect on existing (unchanged) repositories or in combination with I(absent).
|
||||||
|
- Implies runrefresh.
|
||||||
|
required: false
|
||||||
|
default: "no"
|
||||||
|
choices: ["yes", "no"]
|
||||||
|
version_added: "2.2"
|
||||||
|
runrefresh:
|
||||||
|
description:
|
||||||
|
- Refresh the package list of the given repository.
|
||||||
|
- Can be used with repo=* to refresh all repositories.
|
||||||
|
required: false
|
||||||
|
default: "no"
|
||||||
|
choices: ["yes", "no"]
|
||||||
|
version_added: "2.2"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "zypper >= 1.0 # included in openSuSE >= 11.1 or SuSE Linux Enterprise Server/Desktop >= 11.0"
|
- "zypper >= 1.0 # included in openSuSE >= 11.1 or SuSE Linux Enterprise Server/Desktop >= 11.0"
|
||||||
'''
|
'''
|
||||||
|
@ -93,6 +114,15 @@ EXAMPLES = '''
|
||||||
|
|
||||||
# Add python development repository
|
# Add python development repository
|
||||||
- zypper_repository: repo=http://download.opensuse.org/repositories/devel:/languages:/python/SLE_11_SP3/devel:languages:python.repo
|
- zypper_repository: repo=http://download.opensuse.org/repositories/devel:/languages:/python/SLE_11_SP3/devel:languages:python.repo
|
||||||
|
|
||||||
|
# Refresh all repos
|
||||||
|
- zypper_repository: repo=* runrefresh=yes
|
||||||
|
|
||||||
|
# Add a repo and add it's gpg key
|
||||||
|
- zypper_repository: repo=http://download.opensuse.org/repositories/systemsmanagement/openSUSE_Leap_42.1/ auto_import_keys=yes
|
||||||
|
|
||||||
|
# Force refresh of a repository
|
||||||
|
- zypper_repository: repo=http://my_internal_ci_repo/repo name=my_ci_repo state=present runrefresh=yes
|
||||||
'''
|
'''
|
||||||
|
|
||||||
REPO_OPTS = ['alias', 'name', 'priority', 'enabled', 'autorefresh', 'gpgcheck']
|
REPO_OPTS = ['alias', 'name', 'priority', 'enabled', 'autorefresh', 'gpgcheck']
|
||||||
|
@ -121,14 +151,10 @@ def _parse_repos(module):
|
||||||
elif rc == 6:
|
elif rc == 6:
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
d = { 'zypper_exit_code': rc }
|
module.fail_json(msg='Failed to execute "%s"' % " ".join(cmd), rc=rc, stdout=stdout, stderr=stderr)
|
||||||
if stderr:
|
|
||||||
d['stderr'] = stderr
|
|
||||||
if stdout:
|
|
||||||
d['stdout'] = stdout
|
|
||||||
module.fail_json(msg='Failed to execute "%s"' % " ".join(cmd), **d)
|
|
||||||
|
|
||||||
def _repo_changes(realrepo, repocmp):
|
def _repo_changes(realrepo, repocmp):
|
||||||
|
"Check whether the 2 given repos have different settings."
|
||||||
for k in repocmp:
|
for k in repocmp:
|
||||||
if repocmp[k] and k not in realrepo:
|
if repocmp[k] and k not in realrepo:
|
||||||
return True
|
return True
|
||||||
|
@ -144,6 +170,13 @@ def _repo_changes(realrepo, repocmp):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def repo_exists(module, repodata, overwrite_multiple):
|
def repo_exists(module, repodata, overwrite_multiple):
|
||||||
|
"""Check whether the repository already exists.
|
||||||
|
|
||||||
|
returns (exists, mod, old_repos)
|
||||||
|
exists: whether a matching (name, URL) repo exists
|
||||||
|
mod: whether there are changes compared to the existing repo
|
||||||
|
old_repos: list of matching repos
|
||||||
|
"""
|
||||||
existing_repos = _parse_repos(module)
|
existing_repos = _parse_repos(module)
|
||||||
|
|
||||||
# look for repos that have matching alias or url to the one searched
|
# look for repos that have matching alias or url to the one searched
|
||||||
|
@ -171,7 +204,8 @@ def repo_exists(module, repodata, overwrite_multiple):
|
||||||
module.fail_json(msg=errmsg)
|
module.fail_json(msg=errmsg)
|
||||||
|
|
||||||
|
|
||||||
def modify_repo(module, repodata, old_repos, zypper_version, warnings):
|
def addmodify_repo(module, repodata, old_repos, zypper_version, warnings):
|
||||||
|
"Adds the repo, removes old repos before, that would conflict."
|
||||||
repo = repodata['url']
|
repo = repodata['url']
|
||||||
cmd = ['/usr/bin/zypper', 'ar', '--check']
|
cmd = ['/usr/bin/zypper', 'ar', '--check']
|
||||||
if repodata['name']:
|
if repodata['name']:
|
||||||
|
@ -212,24 +246,15 @@ def modify_repo(module, repodata, old_repos, zypper_version, warnings):
|
||||||
remove_repo(module, oldrepo['url'])
|
remove_repo(module, oldrepo['url'])
|
||||||
|
|
||||||
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
|
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
|
||||||
changed = rc == 0
|
return rc, stdout, stderr
|
||||||
if rc == 0:
|
|
||||||
changed = True
|
|
||||||
else:
|
|
||||||
if stderr:
|
|
||||||
module.fail_json(msg=stderr)
|
|
||||||
else:
|
|
||||||
module.fail_json(msg=stdout)
|
|
||||||
|
|
||||||
return changed
|
|
||||||
|
|
||||||
|
|
||||||
def remove_repo(module, repo):
|
def remove_repo(module, repo):
|
||||||
|
"Removes the repo."
|
||||||
cmd = ['/usr/bin/zypper', 'rr', repo]
|
cmd = ['/usr/bin/zypper', 'rr', repo]
|
||||||
|
|
||||||
rc, stdout, stderr = module.run_command(cmd, check_rc=True)
|
rc, stdout, stderr = module.run_command(cmd, check_rc=True)
|
||||||
changed = rc == 0
|
return rc, stdout, stderr
|
||||||
return changed
|
|
||||||
|
|
||||||
|
|
||||||
def get_zypper_version(module):
|
def get_zypper_version(module):
|
||||||
|
@ -238,14 +263,16 @@ def get_zypper_version(module):
|
||||||
return LooseVersion('1.0')
|
return LooseVersion('1.0')
|
||||||
return LooseVersion(stdout.split()[1])
|
return LooseVersion(stdout.split()[1])
|
||||||
|
|
||||||
|
def runrefreshrepo(module, auto_import_keys=False, shortname=None):
|
||||||
|
"Forces zypper to refresh repo metadata."
|
||||||
|
cmd = ['/usr/bin/zypper', 'refresh', '--force']
|
||||||
|
if auto_import_keys:
|
||||||
|
cmd.append('--gpg-auto-import-keys')
|
||||||
|
if shortname is not None:
|
||||||
|
cmd.extend(['-r', shortname])
|
||||||
|
|
||||||
def fail_if_rc_is_null(module, rc, stdout, stderr):
|
rc, stdout, stderr = module.run_command(cmd, check_rc=True)
|
||||||
if rc != 0:
|
return rc, stdout, stderr
|
||||||
#module.fail_json(msg=stderr if stderr else stdout)
|
|
||||||
if stderr:
|
|
||||||
module.fail_json(msg=stderr)
|
|
||||||
else:
|
|
||||||
module.fail_json(msg=stdout)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -254,20 +281,25 @@ def main():
|
||||||
name=dict(required=False),
|
name=dict(required=False),
|
||||||
repo=dict(required=False),
|
repo=dict(required=False),
|
||||||
state=dict(choices=['present', 'absent'], default='present'),
|
state=dict(choices=['present', 'absent'], default='present'),
|
||||||
|
runrefresh=dict(required=False, default='no', type='bool'),
|
||||||
description=dict(required=False),
|
description=dict(required=False),
|
||||||
disable_gpg_check = dict(required=False, default=False, type='bool'),
|
disable_gpg_check = dict(required=False, default=False, type='bool'),
|
||||||
refresh = dict(required=False, default=True, type='bool'),
|
autorefresh = dict(required=False, default=True, type='bool', aliases=['refresh']),
|
||||||
priority = dict(required=False, type='int'),
|
priority = dict(required=False, type='int'),
|
||||||
enabled = dict(required=False, default=True, type='bool'),
|
enabled = dict(required=False, default=True, type='bool'),
|
||||||
overwrite_multiple = dict(required=False, default=False, type='bool'),
|
overwrite_multiple = dict(required=False, default=False, type='bool'),
|
||||||
|
auto_import_keys = dict(required=False, default=False, type='bool'),
|
||||||
),
|
),
|
||||||
supports_check_mode=False,
|
supports_check_mode=False,
|
||||||
|
required_one_of = [['state','runrefresh']],
|
||||||
)
|
)
|
||||||
|
|
||||||
repo = module.params['repo']
|
repo = module.params['repo']
|
||||||
alias = module.params['name']
|
alias = module.params['name']
|
||||||
state = module.params['state']
|
state = module.params['state']
|
||||||
overwrite_multiple = module.params['overwrite_multiple']
|
overwrite_multiple = module.params['overwrite_multiple']
|
||||||
|
auto_import_keys = module.params['auto_import_keys']
|
||||||
|
runrefresh = module.params['runrefresh']
|
||||||
|
|
||||||
zypper_version = get_zypper_version(module)
|
zypper_version = get_zypper_version(module)
|
||||||
warnings = [] # collect warning messages for final output
|
warnings = [] # collect warning messages for final output
|
||||||
|
@ -287,7 +319,7 @@ def main():
|
||||||
repodata['gpgcheck'] = '0'
|
repodata['gpgcheck'] = '0'
|
||||||
else:
|
else:
|
||||||
repodata['gpgcheck'] = '1'
|
repodata['gpgcheck'] = '1'
|
||||||
if module.params['refresh']:
|
if module.params['autorefresh']:
|
||||||
repodata['autorefresh'] = '1'
|
repodata['autorefresh'] = '1'
|
||||||
else:
|
else:
|
||||||
repodata['autorefresh'] = '0'
|
repodata['autorefresh'] = '0'
|
||||||
|
@ -296,6 +328,13 @@ def main():
|
||||||
module.exit_json(changed=False, repodata=repodata, state=state)
|
module.exit_json(changed=False, repodata=repodata, state=state)
|
||||||
|
|
||||||
# Check run-time module parameters
|
# Check run-time module parameters
|
||||||
|
if repo == '*' or alias == '*':
|
||||||
|
if runrefresh:
|
||||||
|
runrefreshrepo(module, auto_import_keys)
|
||||||
|
module.exit_json(changed=False, runrefresh=True)
|
||||||
|
else:
|
||||||
|
module.fail_json(msg='repo=* can only be used with the runrefresh option.')
|
||||||
|
|
||||||
if state == 'present' and not repo:
|
if state == 'present' and not repo:
|
||||||
module.fail_json(msg='Module option state=present requires repo')
|
module.fail_json(msg='Module option state=present requires repo')
|
||||||
if state == 'absent' and not repo and not alias:
|
if state == 'absent' and not repo and not alias:
|
||||||
|
@ -310,18 +349,28 @@ def main():
|
||||||
|
|
||||||
exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)
|
exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)
|
||||||
|
|
||||||
|
if repo:
|
||||||
|
shortname = repo
|
||||||
|
else:
|
||||||
|
shortname = alias
|
||||||
|
|
||||||
if state == 'present':
|
if state == 'present':
|
||||||
if exists and not mod:
|
if exists and not mod:
|
||||||
|
if runrefresh:
|
||||||
|
runrefreshrepo(module, auto_import_keys, shortname)
|
||||||
exit_unchanged()
|
exit_unchanged()
|
||||||
changed = modify_repo(module, repodata, old_repos, zypper_version, warnings)
|
rc, stdout, stderr = addmodify_repo(module, repodata, old_repos, zypper_version, warnings)
|
||||||
|
if rc == 0 and (runrefresh or auto_import_keys):
|
||||||
|
runrefreshrepo(module, auto_import_keys, shortname)
|
||||||
elif state == 'absent':
|
elif state == 'absent':
|
||||||
if not exists:
|
if not exists:
|
||||||
exit_unchanged()
|
exit_unchanged()
|
||||||
if not repo:
|
rc, stdout, stderr = remove_repo(module, shortname)
|
||||||
repo=alias
|
|
||||||
changed = remove_repo(module, repo)
|
|
||||||
|
|
||||||
module.exit_json(changed=changed, repodata=repodata, state=state, warnings=warnings)
|
if rc == 0:
|
||||||
|
module.exit_json(changed=True, repodata=repodata, state=state, warnings=warnings)
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Zypper failed with rc %s" % rc, rc=rc, stdout=stdout, stderr=stderr, repodata=repodata, state=state, warnings=warnings)
|
||||||
|
|
||||||
# import module snippets
|
# import module snippets
|
||||||
from ansible.module_utils.basic import *
|
from ansible.module_utils.basic import *
|
||||||
|
|
Loading…
Reference in a new issue