Skip to content

Commit

Permalink
MANOPD-70560 Fix cached packages list in inventory (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
iLeonidze authored Nov 24, 2021
1 parent 771bae0 commit ccdd3e4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 27 deletions.
3 changes: 3 additions & 0 deletions kubetool/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ def install(group: NodeGroup, enable_service: bool = True, force: bool = False)
log.verbose('Searching for already installed auditd package...')
debian_group = group.get_subgroup_with_os('debian')
debian_package_name = cluster.get_package_association_str_for_group(debian_group, 'audit', 'package_name')
if isinstance(debian_package_name, list):
raise Exception(f'Audit can not be installed, because nodes already contains different package versions: '
f'{str(debian_package_name)}')
audit_installed_results = packages.detect_installed_package_version(debian_group, debian_package_name)
log.verbose(audit_installed_results)

Expand Down
2 changes: 1 addition & 1 deletion kubetool/core/annotations.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from kubetool.core.group import NodeGroup


def restrict_multi_os_group(fn):
def restrict_multi_os_group(fn: callable):
"""
Method is an annotation that does not allow origin method to use different OS families in the same group.
:param fn: Origin function to apply annotation validation to
Expand Down
62 changes: 36 additions & 26 deletions kubetool/core/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,21 @@ def get_associations_for_node(self, host: str) -> dict:
node_os_family = self.get_os_family_for_node(host)
return self.get_associations_for_os(node_os_family)

def get_package_association_for_node(self, host: str, package: str, association_key: str) -> str:
def get_package_association_for_node(self, host: str, package: str, association_key: str) -> str or list:
"""
Returns the specified association for the specified package from inventory for specific node
:param host: The address of the node for which required to find the association
:param package: The package name to get the association for
:param association_key: Association key to get
:return: Association string value
:return: Association string or list value
"""
associations = self.get_associations_for_node(host)
association_value = associations.get(package, {}).get(association_key)
if association_value is None:
raise Exception(f'Failed to get association "{association_key}" for package "{package}"')
if not isinstance(association_value, str) and not isinstance(association_value, list):
raise Exception(f'Unsupported association "{association_key}" value type for package "{package}", '
f'got: {str(association_value)}')
return association_value

def get_package_association_for_group(self, group: NodeGroup, package: str, association_key: str) -> dict:
Expand All @@ -239,14 +242,15 @@ def get_package_association_for_group(self, group: NodeGroup, package: str, asso
results[node['connect_to']] = association_value
return results

def get_package_association_str_for_group(self, group: NodeGroup, package: str, association_key: str) -> str:
def get_package_association_str_for_group(self, group: NodeGroup,
package: str, association_key: str) -> str or list:
"""
Returns the specified association string for the specified package from inventory for entire NodeGroup. If
association value is different between some nodes, an exception will be thrown.
Returns the specified association string or list for the specified package from inventory for entire NodeGroup.
If association value is different between some nodes, an exception will be thrown.
:param group: NodeGroup for which required to find the association
:param package: The package name to get the association for
:param association_key: Association key to get
:return: Association string value
:return: Association string or list value
"""
results = self.get_package_association_for_group(group, package, association_key)
results_values = list(set(results.values()))
Expand All @@ -265,40 +269,46 @@ def cache_package_versions(self):
final_packages_list = []
if isinstance(associated_packages, str):
packages_list.append(associated_packages)
else:
elif isinstance(associated_packages, list):
packages_list = packages_list + associated_packages
else:
raise Exception('Unsupported associated packages object type')

for package in packages_list:
detected_package_versions = list(detected_packages[package].keys())
for version in detected_package_versions:
if "not installed" in version:
# if not installed somewhere - just skip
final_packages_list.append(package)
continue
if len(detected_package_versions) == 1:
final_packages_list.append(detected_package_versions[0])
else:
# if detected multiple versions, then such broken package should be skipped
final_packages_list.append(package)
# add package version to list only if it was found as installed
if "not installed" not in version:
final_packages_list.append(version)

# if there no versions detected, then set package version to default
if not final_packages_list:
final_packages_list = [package]

# if non-multiple value, then convert to simple string
# packages can contain multiple package values, like docker package
# (it has docker-ce, docker-cli and containerd.io packages for installation)
if len(final_packages_list) == 1:
final_packages_list = final_packages_list[0]
else:
final_packages_list = list(set(final_packages_list))

associated_params['package_name'] = final_packages_list
# packages from direct installation section
if self.inventory['services']['packages']['install']:
final_packages_list = []
for package in self.inventory['services']['packages']['install']['include']:
package_versions_list = []
detected_package_versions = list(detected_packages[package].keys())
for version in detected_package_versions:
if "not installed" in version:
# if not installed somewhere - just skip
final_packages_list.append(package)
continue
if len(detected_package_versions) == 1:
final_packages_list.append(detected_package_versions[0])
else:
# if detected multiple versions, then such broken package should be skipped
final_packages_list.append(package)
self.inventory['services']['packages']['install']['include'] = final_packages_list
if "not installed" not in version:
# add package version to list only if it was found as installed
package_versions_list.append(version)
# if there no versions detected, then set package version to default
if not package_versions_list:
package_versions_list = [package]
final_packages_list = final_packages_list + package_versions_list
self.inventory['services']['packages']['install']['include'] = list(set(final_packages_list))
return detected_packages

def finish(self):
Expand Down

0 comments on commit ccdd3e4

Please sign in to comment.