diff --git a/README.md b/README.md index 33c2590..0caac11 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,12 @@ Settings to apply to all pulp servers servers - `git_repo_config_dir`: Directory in `git_repo_config` which contains the pulp repo config +- `internal_package_prefix`: Prefix for indicating an internal package uploaded + directly to Pulp primary (no remote URL). +- `package_name_replacement_pattern`: Regex for matching packages to be + renamed. Use named matching groups for use in the format rule. +- `package_name_replacement_rule`: The new name pattern assigned to packages + which match the above. Reference named matching groups from above if needed. - `remote_tls_validation`: Boolean whether to require TLS validation of remote hosts - `use_https_for_sync`: Boolean whether to use HTTPS for repository sync URLs. diff --git a/pulp_manager/app/services/pulp_manager.py b/pulp_manager/app/services/pulp_manager.py index 7cca788..5d22c97 100644 --- a/pulp_manager/app/services/pulp_manager.py +++ b/pulp_manager/app/services/pulp_manager.py @@ -180,7 +180,7 @@ def _process_package_name(self, name: str, base_url: str): package_rename_config = { "pattern": re.compile(pattern), - "replacement_rule": re.compile(replacement) + "replacement_rule": replacement } pattern = package_rename_config['pattern'] replacement_rule = package_rename_config['replacement_rule'] diff --git a/pulp_manager/app/services/repo_config_register.py b/pulp_manager/app/services/repo_config_register.py index f915bd8..2ce1b11 100644 --- a/pulp_manager/app/services/repo_config_register.py +++ b/pulp_manager/app/services/repo_config_register.py @@ -157,6 +157,24 @@ def _generate_repo_config_from_file(self, file_path: str): return repo_config + def _apply_repo_name_prefix(self, name: str, root_path: str) -> str: + """Applies the appropriate prefix to a repo name based on whether it's remote or internal. + + :param name: The repo name + :type name: str + :param root_path: The root directory path containing the repo config file + :type root_path: str + :return: The repo name with appropriate prefix applied + :rtype: str + """ + if "remote" in root_path and not name.startswith("ext-"): + return f"ext-{name}" + elif "internal" in root_path: + prefix = CONFIG["pulp"]["internal_package_prefix"] + if not name.startswith(prefix): + return f"{prefix}{name}" + return name + def _parse_repo_config_files(self, repo_config_dir: str, regex_include: str, regex_exclude: str): """Parses the repo configs in the given repo_config_dir and returns a list of dicts @@ -180,10 +198,7 @@ def _parse_repo_config_files(self, repo_config_dir: str, regex_include: str, repo_config = json.loads(repo_config_file.read()) name = repo_config["name"] - if "remote" in root and not name.startswith("ext-"): - name = f"ext-{name}" - elif "internal" in root and not name.startswith(CONFIG["pulp"]["internal_package_prefix"]): - name = f"{CONFIG['pulp']['internal_package_prefix']}{name}" + name = self._apply_repo_name_prefix(name, root) if regex_exclude and re.search(regex_exclude, name): continue diff --git a/pulp_manager/tests/unit/services/test_pulp_manager.py b/pulp_manager/tests/unit/services/test_pulp_manager.py index c9feece..97f389c 100644 --- a/pulp_manager/tests/unit/services/test_pulp_manager.py +++ b/pulp_manager/tests/unit/services/test_pulp_manager.py @@ -12,6 +12,7 @@ RpmRemote, RpmRepository, SigningService) from pulp3_bindings.pulp3.resources import Task as Pulp3Task +from pulp_manager.app.config import CONFIG from pulp_manager.app.database import engine, session from pulp_manager.app.exceptions import PulpManagerError, PulpManagerValueError from pulp_manager.app.models import PulpServer @@ -948,3 +949,43 @@ def new_pulp_client(pulp_server: PulpServer): self.pulp_manager.add_repos_from_pulp_server("source", None, None) assert mock_create_or_update_repository_source_pulp_server.call_count == 2 + + def test_process_package_name_no_pattern(self): + """Tests that when no pattern is configured, the original name with base_url is returned + """ + CONFIG["pulp"]["package_name_replacement_pattern"] = "" + CONFIG["pulp"]["package_name_replacement_rule"] = "" + + result = self.pulp_manager._process_package_name("test-package", "http://example.com/") + + assert result == "http://example.com/test-package" + + def test_process_package_name_pattern_no_match(self): + """Tests that when pattern doesn't match, the original name with base_url is returned + """ + CONFIG["pulp"]["package_name_replacement_pattern"] = "^prefix-(?P.+)$" + CONFIG["pulp"]["package_name_replacement_rule"] = "{name}-suffix" + + result = self.pulp_manager._process_package_name("no-prefix-package", "http://example.com/") + + assert result == "http://example.com/no-prefix-package" + + def test_process_package_name_pattern_match(self): + """Tests that when pattern matches, the transformed name with base_url is returned + """ + CONFIG["pulp"]["package_name_replacement_pattern"] = "^prefix-(?P.+)$" + CONFIG["pulp"]["package_name_replacement_rule"] = "{name}-suffix" + + result = self.pulp_manager._process_package_name("prefix-mypackage", "http://example.com/") + + assert result == "http://example.com/mypackage-suffix" + + def test_process_package_name_complex_pattern(self): + """Tests package name transformation with multiple named groups + """ + CONFIG["pulp"]["package_name_replacement_pattern"] = "^(?P[a-z]+)-(?P[a-z]+)-(?P.+)$" + CONFIG["pulp"]["package_name_replacement_rule"] = "{env}/{org}/{pkg}" + + result = self.pulp_manager._process_package_name("acme-prod-webserver", "http://example.com/") + + assert result == "http://example.com/prod/acme/webserver" diff --git a/pulp_manager/tests/unit/services/test_repo_config_register.py b/pulp_manager/tests/unit/services/test_repo_config_register.py index fd93ac2..df45e8c 100644 --- a/pulp_manager/tests/unit/services/test_repo_config_register.py +++ b/pulp_manager/tests/unit/services/test_repo_config_register.py @@ -8,6 +8,7 @@ import pytest from mock import mock_open, patch +from pulp_manager.app.config import CONFIG from pulp_manager.app.database import engine, session from pulp_manager.app.services.repo_config_register import RepoConfigRegister @@ -212,6 +213,40 @@ def open_side_effect(name, mode=None): assert len(parsed_repo_configs) == 1 assert parsed_repo_configs[0]["name"] == "ext-el8repo" + def test_apply_repo_name_prefix_remote(self): + """Tests that _apply_repo_name_prefix adds 'ext-' prefix for remote repos + """ + CONFIG["pulp"]["internal_package_prefix"] = "int_" + + # Remote repo without prefix + result = self.repo_config_register._apply_repo_name_prefix("myrepo", "/path/remote/el7") + assert result == "ext-myrepo" + + # Remote repo already with prefix + result = self.repo_config_register._apply_repo_name_prefix("ext-myrepo", "/path/remote/el7") + assert result == "ext-myrepo" + + def test_apply_repo_name_prefix_internal(self): + """Tests that _apply_repo_name_prefix adds internal_package_prefix for internal repos + """ + CONFIG["pulp"]["internal_package_prefix"] = "int_" + + # Internal repo without prefix + result = self.repo_config_register._apply_repo_name_prefix("myrepo", "/path/internal/el7") + assert result == "int_myrepo" + + # Internal repo already with prefix + result = self.repo_config_register._apply_repo_name_prefix("int_myrepo", "/path/internal/el7") + assert result == "int_myrepo" + + def test_apply_repo_name_prefix_neither(self): + """Tests that _apply_repo_name_prefix returns original name for repos not in remote or internal paths + """ + CONFIG["pulp"]["internal_package_prefix"] = "int_" + + result = self.repo_config_register._apply_repo_name_prefix("myrepo", "/path/other/el7") + assert result == "myrepo" + @patch("pulp_manager.app.services.repo_config_register.Repo.clone_from") def test_create_repos_from_git_config_fail(self, mock_clone_from): """Tests logic flow that if they are errors an exception is raised