Skip to content

Commit 4b853bd

Browse files
authored
Merge pull request #588 from gerrod3/proxy-sync-fix
Fix syncing with proxies
2 parents f15a9bf + 2016bc1 commit 4b853bd

File tree

3 files changed

+63
-22
lines changed

3 files changed

+63
-22
lines changed

CHANGES/581.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed syncing ignoring remote proxy.

pulp_python/app/tasks/sync.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from aiohttp import ClientResponseError, ClientError
44
from lxml.etree import LxmlError
55
from gettext import gettext as _
6-
from os import environ
6+
from os import environ, path
77

88
from rest_framework import serializers
99

@@ -26,7 +26,7 @@
2626
from bandersnatch.master import Master
2727
from bandersnatch.configuration import BandersnatchConfig
2828
from packaging.requirements import Requirement
29-
from urllib.parse import urljoin
29+
from urllib.parse import urljoin, urlsplit, urlunsplit
3030

3131
logger = logging.getLogger(__name__)
3232

@@ -111,14 +111,22 @@ async def run(self):
111111
"""
112112
If includes is specified, then only sync those,else try to sync all other packages
113113
"""
114+
# Prevent bandersnatch from reading actual .netrc file, set to nonexistent file
115+
# See discussion on https://github.com/pulp/pulp_python/issues/581
116+
environ["NETRC"] = f"{path.curdir}/.fake-netrc"
114117
# TODO Change Bandersnatch internal API to take proxy settings in from config parameters
115-
if self.remote.proxy_url:
116-
environ['http_proxy'] = self.remote.proxy_url
117-
environ['https_proxy'] = self.remote.proxy_url
118+
if proxy_url := self.remote.proxy_url:
119+
if self.remote.proxy_username or self.remote.proxy_password:
120+
parsed_proxy = urlsplit(proxy_url)
121+
creds = f"{self.remote.proxy_username}:{self.remote.proxy_password}"
122+
netloc = f"{creds}@{parsed_proxy.netloc}"
123+
proxy_url = urlunsplit((parsed_proxy.scheme, netloc, "", "", ""))
124+
environ['http_proxy'] = proxy_url
125+
environ['https_proxy'] = proxy_url
118126
# Bandersnatch includes leading slash when forming API urls
119127
url = self.remote.url.rstrip("/")
120128
# local & global timeouts defaults to 10secs and 5 hours
121-
async with PulpMaster(url) as master:
129+
async with Master(url) as master:
122130
deferred_download = self.remote.policy != Remote.IMMEDIATE
123131
workers = self.remote.download_concurrency or self.remote.DEFAULT_DOWNLOAD_CONCURRENCY
124132
async with ProgressReport(
@@ -140,18 +148,6 @@ async def run(self):
140148
await pmirror.synchronize(packages_to_sync)
141149

142150

143-
class PulpMaster(Master):
144-
"""
145-
Temporary subclass of bandersnatch.Master until features are in bandersnatch.
146-
"""
147-
148-
async def __aenter__(self) -> "Master":
149-
"""Ensure Pulp does not try to read the .netrc file."""
150-
await super().__aenter__()
151-
self.session._trust_env = False
152-
return self
153-
154-
155151
class PulpMirror(Mirror):
156152
"""
157153
Pulp Mirror Class to perform syncing using Bandersnatch

pulp_python/tests/functional/api/test_sync.py

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# coding=utf-8
22
"""Tests that sync python plugin repositories."""
3+
import pytest
34
import unittest
45

56
from pulp_smash import config
6-
from pulp_smash.pulp3.bindings import monitor_task, PulpTaskError, delete_orphans
7+
from pulp_smash.pulp3.bindings import monitor_task, PulpTaskError
78
from pulp_smash.pulp3.utils import (
89
gen_repo,
910
get_added_content_summary,
@@ -582,9 +583,6 @@ def tearDown(cls):
582583
"""Destroy class-wide variables per test"""
583584
cls.remote_api.delete(cls.remote.pulp_href)
584585
cls.repo_api.delete(cls.repo.pulp_href)
585-
# This is the last test case to be ran, delete orphans
586-
# TODO: Move this to pytest hook when converting to pytest style
587-
delete_orphans()
588586

589587
def test_no_windows_sync(self):
590588
"""Tests that no windows packages are synced"""
@@ -643,6 +641,52 @@ def test_no_platform_sync(self):
643641
)
644642

645643

644+
@pytest.mark.parallel
645+
def test_proxy_sync(
646+
python_repo,
647+
python_repo_api_client,
648+
python_remote_factory,
649+
python_content_api_client,
650+
http_proxy,
651+
):
652+
"""Test syncing with a proxy."""
653+
body = gen_python_remote(proxy_url=http_proxy.proxy_url)
654+
remote = python_remote_factory(**body)
655+
sync_resp = python_repo_api_client.sync(python_repo.pulp_href, {"remote": remote.pulp_href})
656+
monitor_task(sync_resp.task)
657+
658+
repo = python_repo_api_client.read(python_repo.pulp_href)
659+
assert repo.latest_version_href[-2] == "1"
660+
661+
content_resp = python_content_api_client.list(repository_version=repo.latest_version_href)
662+
assert content_resp.count == 2
663+
664+
665+
@pytest.mark.parallel
666+
def test_proxy_auth_sync(
667+
python_repo,
668+
python_repo_api_client,
669+
python_remote_factory,
670+
python_content_api_client,
671+
http_proxy_with_auth,
672+
):
673+
"""Test syncing with a proxy with auth."""
674+
body = gen_python_remote(
675+
proxy_url=http_proxy_with_auth.proxy_url,
676+
proxy_username=http_proxy_with_auth.username,
677+
proxy_password=http_proxy_with_auth.password,
678+
)
679+
remote = python_remote_factory(**body)
680+
sync_resp = python_repo_api_client.sync(python_repo.pulp_href, {"remote": remote.pulp_href})
681+
monitor_task(sync_resp.task)
682+
683+
repo = python_repo_api_client.read(python_repo.pulp_href)
684+
assert repo.latest_version_href[-2] == "1"
685+
686+
content_resp = python_content_api_client.list(repository_version=repo.latest_version_href)
687+
assert content_resp.count == 2
688+
689+
646690
def sync_to_remote(self, body, create=False, mirror=False):
647691
"""Takes a body and creates/updates a remote object, then it performs a sync"""
648692
if create:

0 commit comments

Comments
 (0)