From a49a3ea988371dbe018b218f53e8f1c737af2e0d Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Thu, 29 Aug 2024 21:39:07 -0400 Subject: [PATCH] feat(provider): use standard library to get proxies (#426) Fixes #422 --- craft_application/services/provider.py | 10 +++-- tests/unit/services/test_provider.py | 53 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/craft_application/services/provider.py b/craft_application/services/provider.py index 7ca9e51c..fe12c012 100644 --- a/craft_application/services/provider.py +++ b/craft_application/services/provider.py @@ -22,6 +22,8 @@ import pathlib import pkgutil import sys +import urllib.request +from collections.abc import Generator, Iterable from pathlib import Path from typing import TYPE_CHECKING @@ -36,8 +38,6 @@ from craft_application.util import platforms, snap_config if TYPE_CHECKING: # pragma: no cover - from collections.abc import Generator - import craft_providers from craft_application import models @@ -45,7 +45,7 @@ from craft_application.services import ServiceFactory -DEFAULT_FORWARD_ENVIRONMENT_VARIABLES = ("http_proxy", "https_proxy", "no_proxy") +DEFAULT_FORWARD_ENVIRONMENT_VARIABLES: Iterable[str] = () class ProviderService(base.ProjectService): @@ -93,6 +93,10 @@ def setup(self) -> None: if name in os.environ: self.environment[name] = os.getenv(name) + for scheme, value in urllib.request.getproxies().items(): + self.environment[f"{scheme.lower()}_proxy"] = value + self.environment[f"{scheme.upper()}_PROXY"] = value + if self._install_snap: channel = ( None diff --git a/tests/unit/services/test_provider.py b/tests/unit/services/test_provider.py index 68b20454..17f71814 100644 --- a/tests/unit/services/test_provider.py +++ b/tests/unit/services/test_provider.py @@ -30,6 +30,59 @@ from craft_providers.actions.snap_installer import Snap +@pytest.mark.parametrize( + ("given_environment", "expected_environment"), + [ + ({}, {}), + ({"http_proxy": "thing"}, {"http_proxy": "thing", "HTTP_PROXY": "thing"}), + ({"HTTP_PROXY": "thing"}, {"http_proxy": "thing", "HTTP_PROXY": "thing"}), + ({"ssh_proxy": "thing"}, {"ssh_proxy": "thing", "SSH_PROXY": "thing"}), + ({"no_proxy": "thing"}, {"no_proxy": "thing", "NO_PROXY": "thing"}), + ({"NO_PROXY": "thing"}, {"no_proxy": "thing", "NO_PROXY": "thing"}), + # Special case handled by upstream: + # https://docs.python.org/3/library/urllib.request.html#urllib.request.getproxies + ( + { + "REQUEST_METHOD": "GET", + "HTTP_PROXY": "thing", + }, + {}, + ), + ( # But lower-case http_proxy is still allowed + { + "REQUEST_METHOD": "GET", + "http_proxy": "thing", + }, + {"http_proxy": "thing", "HTTP_PROXY": "thing"}, + ), + ], +) +def test_setup_proxy_environment( + monkeypatch: pytest.MonkeyPatch, + app_metadata, + fake_services, + fake_project, + fake_build_plan, + given_environment: dict[str, str], + expected_environment: dict[str, str], +): + for var, value in given_environment.items(): + monkeypatch.setenv(var, value) + + expected_environment |= {"CRAFT_MANAGED_MODE": "1"} + + service = provider.ProviderService( + app_metadata, + fake_services, + project=fake_project, + work_dir=pathlib.Path(), + build_plan=fake_build_plan, + ) + service.setup() + + assert service.environment == expected_environment + + @pytest.mark.parametrize( ("install_snap", "environment", "snaps"), [