Skip to content
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

Establish atix main #1

Open
wants to merge 24 commits into
base: atix-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
221d1f2
[ATIX] Add DebProfile to Profilemanager
Aug 1, 2019
5432dc2
[ATIX] Move repofile to rhsm subpackage
Aug 8, 2019
5abc786
[ATIX] Generate enabled_repos from repofile
Aug 8, 2019
90a4243
[ATIX] Fix report enabled deb-repositories only
m-bucher Oct 20, 2020
db6bcdc
[ATIX] Allow syspurpose file to be written
sbernhard Dec 7, 2021
4f6026d
[ATIX] Add handling of params in repository urls
hstct Jan 17, 2023
e86d256
[ATIX] Use repofile from rhsm subpackage
goarsna Jun 28, 2023
3f9ba06
[ATIX] Remove failing method annotations
goarsna Jun 28, 2023
2aed02b
[ATIX] Adjust katello script for Python3
goarsna Jun 28, 2023
850ccc8
[ATIX] Fix APT component selection
quba42 Jul 3, 2023
f408516
[ATIX] Fix failing profile upload with SCA enabled
m-bucher Feb 2, 2024
f79cf5f
[ATIX] Add deb repo-setting Signed-By
m-bucher May 24, 2024
8c8167a
WIP Fix setup.py style
sbernhard Jul 29, 2024
c871278
WIP Fix baseurl style in profile
sbernhard Jul 29, 2024
09c01db
WIP Fix debprofile style in profile
sbernhard Jul 29, 2024
1c6f311
WIP Fix repofile style
sbernhard Jul 29, 2024
ba92938
WIP Fix cache style
sbernhard Jul 29, 2024
7ca91fb
WIP Fix syspurpose style
sbernhard Jul 29, 2024
0f6741a
WIP - fix tests. repofile moved from sub-man to rhsm
sbernhard Aug 1, 2024
085b20e
WIP: fix repolib tests for apt. mock apt
sbernhard Aug 1, 2024
a15dad4
WIP: fix repofile.py - the /etc/apt/trusted.gpg.d dir may not exist
sbernhard Aug 2, 2024
752175a
WIP: setup.py package profile update packaged twice
sbernhard Aug 2, 2024
9273491
fix test
sbernhard Aug 8, 2024
214d088
WIP: fix repofile mappings.items() issue
sbernhard Aug 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion debian-stuff/80package-profile-upload
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DPkg::Post-Invoke { /usr/lib/katello-client/bin/deb_package_profile_upload }
DPkg::Post-Invoke { /usr/bin/package-profile-upload }
35 changes: 0 additions & 35 deletions debian-stuff/deb_package_profile_upload

This file was deleted.

1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ def find_py(self):
entry_points={
"console_scripts": [
"subscription-manager = subscription_manager.scripts.subscription_manager:main",
'package-profile-upload = subscription_manager.scripts.package_profile_upload:main',
"rct = subscription_manager.scripts.rct:main",
"rhsm-debug = subscription_manager.scripts.rhsm_debug:main",
"rhsm-facts-service = subscription_manager.scripts.rhsm_facts_service:main",
Expand Down
147 changes: 49 additions & 98 deletions src/rhsm/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,36 @@

import importlib.util
import rpm
import os.path
from typing import List, Union

from rhsm import ourjson as json
from rhsm.utils import suppress_output
from iniparse import SafeConfigParser, ConfigParser
from rhsm.repofile import get_repo_file_classes
from cloud_what import provider

try:
import dnf
from rhsm.repofile import dnf
except ImportError:
dnf = None

try:
import libdnf
from rhsm.repofile import libdnf
except ImportError:
libdnf = None

try:
import yum
from rhsm.repofile import yum
except ImportError:
yum = None

try:
from rhsm.repofile import apt
except ImportError:
apt = None

use_zypper: bool = importlib.util.find_spec("zypp_plugin") is not None


if use_zypper:
REPOSITORY_PATH = "/etc/rhsm/zypper.repos.d/redhat.repo"
else:
Expand Down Expand Up @@ -191,111 +196,28 @@ def collect(self) -> List[dict]:
return self.content


class EnabledRepos:
def __generate(self) -> List[dict]:
if not os.path.exists(self.repofile):
return []

# Unfortuantely, we can not use the SafeConfigParser for zypper repo
# files because the repository urls contains strings which the
# SafeConfigParser don't like. It would crash with
# ConfigParser.InterpolationSyntaxError: '%' must be followed by '%' or '('
if use_zypper:
config = ConfigParser()
else:
config = SafeConfigParser()
config.read(self.repofile)
enabled_sections = [section for section in config.sections() if config.getboolean(section, "enabled")]
enabled_repos = []
for section in enabled_sections:
try:
enabled_repos.append(
{
"repositoryid": section,
"baseurl": [self._format_baseurl(config.get(section, "baseurl"))],
}
)
except ImportError:
break
return enabled_repos

def __init__(self, repo_file: str) -> None:
"""
Initialize EnabledRepos
:param repo_file: A repo file path used to filter the report.
"""
if dnf is not None:
self.db = dnf.dnf.Base()
elif yum is not None:
self.yb = yum.YumBase()

self.repofile: str = repo_file
self.content: List[dict] = self.__generate()

def __str__(self) -> str:
return str(self.content)

def _format_baseurl(self, repo_url: str) -> str:
"""
Returns a well formatted baseurl string
:param repo_url: a repo URL that you want to format
"""
if use_zypper:
return self._cut_question_mark(repo_url)
else:
mappings = self._obtain_mappings()
return repo_url.replace("$releasever", mappings["releasever"]).replace(
"$basearch", mappings["basearch"]
)

def _cut_question_mark(self, repo_url) -> str:
"""
Returns a string where everything after the first occurrence of '?' is truncated
:param repo_url: a repo URL that you want to modify
"""
return repo_url[: repo_url.find("?")]

@suppress_output
def _obtain_mappings(self) -> dict:
"""
returns a hash with "basearch" and "releasever" set. This will try dnf first, and them yum if dnf is
not installed.
"""
if dnf is not None:
return self._obtain_mappings_dnf()
elif yum is not None:
return self._obtain_mappings_yum()
else:
log.error("Unable to load module for any supported package manager (dnf, yum).")
raise ImportError

def _obtain_mappings_dnf(self) -> dict:
return {
"releasever": self.db.conf.substitutions["releasever"],
"basearch": self.db.conf.substitutions["basearch"],
}

def _obtain_mappings_yum(self) -> dict:
return {"releasever": self.yb.conf.yumvar["releasever"], "basearch": self.yb.conf.yumvar["basearch"]}


class EnabledReposProfile:
"""
Collect information about enabled repositories
"""

def __init__(self, repo_file: str = REPOSITORY_PATH) -> None:
self._enabled_repos: EnabledRepos = EnabledRepos(repo_file)
self._content = []
for repo_file_cls, _ in get_repo_file_classes():
repo_file = repo_file_cls()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not rather be:
repo_file = repo_file_cls(repo_file)
This might have further implications, since apparently for now this expects to always use the repo_file_cls()'s default-value for path

repo_file.read()
self._content.extend(repo_file.enabled_repos())
self._content.sort(key=lambda x: x['baseurl'])

def __eq__(self, other: "EnabledReposProfile") -> bool:
return self._enabled_repos.content == other._enabled_repos.content
return self._content == other._content

def collect(self) -> List[dict]:
"""
Gather list of enabled repositories
:return: List of enabled repositories
"""
return self._enabled_repos.content
return self._content


class Package:
Expand Down Expand Up @@ -444,6 +366,30 @@ def __eq__(self, other: "RPMProfile") -> bool:
return True


class DebProfile(object):
def __init__(self):
cache = apt.Cache()
self._deb_profile = [
{
'name': package.name,
'version': package.installed.version,
'architecture': package.installed.architecture
} for package in cache if package.installed is not None
]

def __eq__(self, other):
"""
Compare one profile to another to determine if anything has changed.
"""
if not isinstance(self, type(other)):
return False

return self._deb_profile == other._deb_profile

def collect(self):
return self._deb_profile


def get_profile(profile_type: str) -> Union[RPMProfile, EnabledRepos, ModulesProfile]:
"""
Returns an instance of a Profile object
Expand All @@ -458,7 +404,12 @@ def get_profile(profile_type: str) -> Union[RPMProfile, EnabledRepos, ModulesPro

# Profile types we support:
PROFILE_MAP: dict = {
"rpm": RPMProfile,
"enabled_repos": EnabledReposProfile,
"modulemd": ModulesProfile,
}

if dnf is not None or yum is not None:
PROFILE_MAP["rpm"] = RPMProfile
PROFILE_MAP["modulemd"] = ModulesProfile

if apt is not None:
PROFILE_MAP["deb"] = DebProfile
Loading