Skip to content

Commit

Permalink
WIP - fix package_manager deps listing
Browse files Browse the repository at this point in the history
Fixes: #1455
  • Loading branch information
gdemonet committed Jul 25, 2019
1 parent 4d7b8a7 commit bb181f4
Showing 1 changed file with 113 additions and 35 deletions.
148 changes: 113 additions & 35 deletions salt/_modules/metalk8s_package_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Describes our custom way to deal with yum packages
so that we can support downgrade in metalk8s
'''

import collections
import logging

log = logging.getLogger(__name__)
Expand All @@ -15,64 +15,142 @@ def __virtual__():
return __virtualname__


def list_pkg_deps(pkg_name, version=None, fromrepo=None):
def _list_requires(pkg_name, version, fromrepo=None, versions_dict=None):
'''
Check dependencies related to the packages installed so that we can pass
this information to pkg.installed
name
Name of the package installed
version
Version number of the package
Use : salt '*' metalk8s_package_manager.list_pkg_deps kubelet 1.11.9
List a package requirements without duplications, and check versions
are referenced in `versions_dict` if provided.
'''
log.info(
'Listing deps for "%s" with version "%s"',
'Listing requirements for package "%s" with version "%s"',
str(pkg_name),
str(version)
)
pkgs_dict = {pkg_name: version}

if not version:
return pkgs_dict

command_all = [
'repoquery', '--whatrequires', '--recursive', '--qf',
command = [
'repoquery', '--whatrequires', '--qf',
'%{NAME} %{VERSION}-%{RELEASE}',
'{}-{}'.format(str(pkg_name), str(version))
]

if fromrepo:
command_all.extend(['--disablerepo', '*', '--enablerepo', fromrepo])
command.extend(['--disablerepo', '*', '--enablerepo', fromrepo])

deps_list = __salt__['cmd.run_all'](command_all)
ret = __salt__['cmd.run_all'](command)

if deps_list['retcode'] != 0:
if ret['retcode'] != 0:
log.error(
'Failed to list package dependencies: %s',
deps_list['stderr'] or deps_list['stdout']
'Failed to list package "%s" requirements: %s',
str(pkg_name),
ret['stderr'] or ret['stdout']
)
return None

out = deps_list['stdout'].splitlines()
for line in out:
requirements = collections.defaultdict(list)
for line in ret['stdout'].splitlines():
name, version = line.strip().split()
pkgs_dict[name] = version
requirements[name].append(version)

filtered_requirements = {}
versions_dict = versions_dict or {}

for name, versions in requirements.items():
if name not in versions_dict:
# We pick the first version we found
filtered_requirements[name] = versions[0]
continue

version = versions_dict[name]
if version not in versions:
log.error(
'Package "%s" requires "%s" in one of the following versions: '
'%s. Configured version is %s.',
pkg_name,
name,
', '.join(versions),
version
)
return None

filtered_requirements[name] = version

for name, version in filtered_requirements.items():
extra_requirements = _list_requires(
name, version, fromrepo=fromrepo, versions_dict=versions_dict
)

# We only update with unseen requirements
for pkg_name, pkg_version in extra_requirements.items():
filtered_requirements.setdefault(pkg_name, pkg_version)

return filtered_requirements


def list_pkg_deps(pkg_name, version=None, fromrepo=None, versions_dict=None):
'''
Check dependencies related to the packages installed so that we can pass
this information to pkg.installed.
Ensure all listed versions are compliant with those listed in versions_dict
if provided.
pkg_name
Name of the package installed
version
Version number of the package
for key in pkgs_dict.keys():
package_query = __salt__['cmd.run_all'](
['rpm', '-qa', key]
versions_dict
Dict of all package versions supported
Use : salt '*' metalk8s_package_manager.list_pkg_deps kubelet 1.11.9
'''
versions_dict = versions_dict or {}

if versions_dict and pkg_name not in versions_dict:
log.error(
'Trying to install "%s" which is not referenced in the versions '
'listing provided.',
pkg_name
)
return None

if package_query['retcode'] == 1:
pkgs_dict.pop(key)
elif package_query['retcode'] != 0:
pkgs_dict = {pkg_name: version}

if not version:
return pkgs_dict

if versions_dict and versions_dict[pkg_name] != version:
log.error(
'Trying to install "%s" with version "%s", while version '
'referenced is "%s".',
pkg_name,
version,
versions_dict[pkg_name]
)
return None

requirements = _list_requires(
pkg_name, version, fromrepo=fromrepo, versions_dict=versions_dict
)
pkgs_dict.update(requirements)

for p_name, p_version in pkgs_dict.items():
ret = __salt__['cmd.run_all'](
['rpm', '-qa', p_name, '--queryformat "%{VERSION}-%{RELEASE}"']
)

if ret['retcode'] != 0:
log.error(
'Failed to check if package is installed: %s',
deps_list['stderr'] or deps_list['stdout']
'Failed to check if package "%s" is installed: %s',
p_name,
ret['stderr'] or ret['stdout']
)
return None

installed_version = ret['stdout'].strip()
if p_version == installed_version:
# Only remove the package from the dict if desired version matches
# the one installed
del pkgs_dict[p_name]

return pkgs_dict

0 comments on commit bb181f4

Please sign in to comment.