From 4a724d641ad4819c523c8c68d68d0f4033c762e1 Mon Sep 17 00:00:00 2001 From: Caleigh Runge-Hottman Date: Wed, 23 Sep 2026 09:33:05 -0400 Subject: [PATCH 1/2] Add PUBTOOLS_PULP3_* env var fallbacks [RHELDST-45461] Add environment variable fallbacks for `--pulp3-url` (`PUBTOOLS_PULP3_URL`), `--domain` (`PUBTOOLS_PULP3_DOMAIN`), and `--pulp3-user` (`PUBTOOLS_PULP3_USER`) in `Pulp3ClientService`, and update existing `PULP3_PASSWORD` env var pattern to use a `PUBTOOLS_PULP3_` prefix (as opposed to the generic `PULP3` variant). This allows the Konflux Tekton task to configure Hosted Pulp credentials entirely via env vars. These env vars are also supported by pushsource's KonfluxSource. The pubtools-pulp-push command no longer needs `--pulp3-url`, `--domain`, or `--pulp3-user` CLI args. Though, when provided, CLI args still take precedence over env vars. --- src/pubtools/_pulp/services/pulp3.py | 43 ++++++++++----- tests/shared/test_pulp_task.py | 81 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 12 deletions(-) diff --git a/src/pubtools/_pulp/services/pulp3.py b/src/pubtools/_pulp/services/pulp3.py index 49a314f1..feabb664 100644 --- a/src/pubtools/_pulp/services/pulp3.py +++ b/src/pubtools/_pulp/services/pulp3.py @@ -27,9 +27,21 @@ def add_service_args(self, parser): super(Pulp3ClientService, self).add_service_args(parser) group = parser.add_argument_group("Pulp3 environment") - group.add_argument("--pulp3-url", help="Pulp3 server URL") - group.add_argument("--domain", help="Domain name for Pulp3 server") - group.add_argument("--pulp3-user", help="Pulp3 username", default=None) + group.add_argument( + "--pulp3-url", + help="Pulp3 server URL (or set PULP3_URL environment variable)", + default=None, + ) + group.add_argument( + "--domain", + help="Domain name for Pulp3 server (or set PULP3_DOMAIN environment variable)", + default=None, + ) + group.add_argument( + "--pulp3-user", + help="Pulp3 username (or set PULP3_USER environment variable)", + default=None, + ) group.add_argument( "--pulp3-password", help="Pulp3 password (or set PULP3_PASSWORD environment variable)", @@ -57,7 +69,11 @@ def new_pulp3_client(self): """Creates and returns a new Pulp3 client with appropriate config.""" args = self._service_args auth = cert = None - if not (args.pulp3_url and args.domain): + + pulp3_url = args.pulp3_url or os.environ.get("PUBTOOLS_PULP3_URL") + domain = args.domain or os.environ.get("PUBTOOLS_PULP3_DOMAIN") + + if not (pulp3_url and domain): LOG.error("Both pulp3-url and domain must be provided") sys.exit(41) @@ -72,16 +88,18 @@ def new_pulp3_client(self): cert = (args.pulp3_cert, args.pulp3_cert_key) else: cert = args.pulp3_cert + + pulp3_user = args.pulp3_user or os.environ.get("PUBTOOLS_PULP3_USER") # checks if pulp password is available as environment variable - if args.pulp3_user: - pulp3_password = args.pulp3_password or os.environ.get("PULP3_PASSWORD") + if pulp3_user: + pulp3_password = args.pulp3_password or os.environ.get("PUBTOOLS_PULP3_PASSWORD") if not pulp3_password: - LOG.error("No pulp3 password provided for %s", args.pulp3_user) + LOG.error("No pulp3 password provided for %s", pulp3_user) sys.exit(41) - auth = (args.pulp3_user, pulp3_password) + auth = (pulp3_user, pulp3_password) return pulplib.Pulp3Client( - args.pulp3_url, domain=args.domain, auth=auth, cert=cert + pulp3_url, domain=domain, auth=auth, cert=cert ) def __exit__(self, *exc_details): @@ -93,10 +111,11 @@ def __exit__(self, *exc_details): def get_pulp3_credentials(self): out = None, (None, None) - if self._service_args.pulp3_user: + pulp3_user = self._service_args.pulp3_user or os.environ.get("PUBTOOLS_PULP3_USER") + if pulp3_user: out = "basic", ( - self._service_args.pulp3_user, - self._service_args.pulp3_password or os.environ.get("PULP3_PASSWORD"), + pulp3_user, + self._service_args.pulp3_password or os.environ.get("PUBTOOLS_PULP3_PASSWORD"), ) elif self._service_args.pulp3_cert: diff --git a/tests/shared/test_pulp_task.py b/tests/shared/test_pulp_task.py index d1f29493..46eb58b2 100644 --- a/tests/shared/test_pulp_task.py +++ b/tests/shared/test_pulp_task.py @@ -285,6 +285,87 @@ def test_pulp_missing_args(caplog): assert "At least one of --pulp-url or --pulp-fake must be provided" in caplog.text +def test_pulp3_client_env_vars(monkeypatch): + """Checks that Pulp3 client can be created from PUBTOOLS_PULP3_* env vars alone.""" + monkeypatch.setenv("PUBTOOLS_PULP3_URL", "http://pulp3.env.example.com") + monkeypatch.setenv("PUBTOOLS_PULP3_DOMAIN", "env-domain") + monkeypatch.setenv("PUBTOOLS_PULP3_USER", "env-user") + monkeypatch.setenv("PUBTOOLS_PULP3_PASSWORD", "env-password") + + with TaskWithPulp3Client() as task: + arg = ["", "--pulp-url", "http://some.url"] + with patch("sys.argv", arg): + with patch( + "pubtools._pulp.services.pulp3.pulplib.Pulp3Client" + ) as mock_pulp3_client: + task.pulp3_client + + mock_pulp3_client.assert_called_once_with( + "http://pulp3.env.example.com", + domain="env-domain", + auth=("env-user", "env-password"), + cert=None, + ) + + +def test_pulp3_env_vars_cli_precedence(monkeypatch): + """CLI args take precedence over PUBTOOLS_PULP3_* env vars.""" + monkeypatch.setenv("PUBTOOLS_PULP3_URL", "http://pulp3.env.example.com") + monkeypatch.setenv("PUBTOOLS_PULP3_DOMAIN", "env-domain") + monkeypatch.setenv("PUBTOOLS_PULP3_USER", "env-user") + monkeypatch.setenv("PUBTOOLS_PULP3_PASSWORD", "env-password") + + with TaskWithPulp3Client() as task: + arg = [ + "", + "--pulp-url", + "http://some.url", + "--pulp3-url", + "http://pulp3.cli.example.com", + "--domain", + "cli-domain", + "--pulp3-user", + "cli-user", + "--pulp3-password", + "cli-password", + ] + with patch("sys.argv", arg): + with patch( + "pubtools._pulp.services.pulp3.pulplib.Pulp3Client" + ) as mock_pulp3_client: + task.pulp3_client + + mock_pulp3_client.assert_called_once_with( + "http://pulp3.cli.example.com", + domain="cli-domain", + auth=("cli-user", "cli-password"), + cert=None, + ) + + +def test_pulp3_get_credentials_basic_env_vars(monkeypatch): + """get_pulp3_credentials() reads from PUBTOOLS_PULP3_* env vars.""" + monkeypatch.setenv("PUBTOOLS_PULP3_USER", "env-user") + monkeypatch.setenv("PUBTOOLS_PULP3_PASSWORD", "env-password") + + with TaskWithPulp3Client() as task: + arg = [ + "", + "--pulp-url", + "http://some.url", + "--domain", + "test", + "--pulp3-url", + "http://some.url3", + ] + with patch("sys.argv", arg): + with patch("pubtools._pulp.task.PulpTask.run"): + assert task.get_pulp3_credentials() == ( + "basic", + ("env-user", "env-password"), + ) + + def test_pulp3_missing_args(caplog): """An error occurs if task is invoked with neither --pulp3-url nor --domain.""" From d779b49f9d04163415c3892eea77751d7c878e95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 14:42:02 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pubtools/_pulp/services/pulp3.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pubtools/_pulp/services/pulp3.py b/src/pubtools/_pulp/services/pulp3.py index feabb664..2fe3b720 100644 --- a/src/pubtools/_pulp/services/pulp3.py +++ b/src/pubtools/_pulp/services/pulp3.py @@ -92,15 +92,15 @@ def new_pulp3_client(self): pulp3_user = args.pulp3_user or os.environ.get("PUBTOOLS_PULP3_USER") # checks if pulp password is available as environment variable if pulp3_user: - pulp3_password = args.pulp3_password or os.environ.get("PUBTOOLS_PULP3_PASSWORD") + pulp3_password = args.pulp3_password or os.environ.get( + "PUBTOOLS_PULP3_PASSWORD" + ) if not pulp3_password: LOG.error("No pulp3 password provided for %s", pulp3_user) sys.exit(41) auth = (pulp3_user, pulp3_password) - return pulplib.Pulp3Client( - pulp3_url, domain=domain, auth=auth, cert=cert - ) + return pulplib.Pulp3Client(pulp3_url, domain=domain, auth=auth, cert=cert) def __exit__(self, *exc_details): # Note: The pulp3_client is an async context manager and must be @@ -111,11 +111,14 @@ def __exit__(self, *exc_details): def get_pulp3_credentials(self): out = None, (None, None) - pulp3_user = self._service_args.pulp3_user or os.environ.get("PUBTOOLS_PULP3_USER") + pulp3_user = self._service_args.pulp3_user or os.environ.get( + "PUBTOOLS_PULP3_USER" + ) if pulp3_user: out = "basic", ( pulp3_user, - self._service_args.pulp3_password or os.environ.get("PUBTOOLS_PULP3_PASSWORD"), + self._service_args.pulp3_password + or os.environ.get("PUBTOOLS_PULP3_PASSWORD"), ) elif self._service_args.pulp3_cert: