Skip to content

Commit 5e4fa4b

Browse files
committed
Fix Python 3.11+ test failures
- Add "backports" module to test_thin.py mocks for Python 3.11+ - Change Docker IPv6 network from 2001:db8::/64 to fd00:db8::/64 with NAT to fix Python 3.11+ timeout issues when connecting to PyPI - Add RELENV_DATA environment variable to test-action.yml (missing from merge forward) - Improve virtualenv creation: check for python3 first, add toolchain to PATH - Simplify importlib_metadata import in _compat.py
1 parent 38a20bf commit 5e4fa4b

File tree

4 files changed

+56
-23
lines changed

4 files changed

+56
-23
lines changed

.github/workflows/test-action.yml

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ on:
5959

6060
env:
6161
COLUMNS: 190
62+
RELENV_DATA: "${{ github.workspace }}/.relenv"
6263
PIP_INDEX_URL: ${{ vars.PIP_INDEX_URL }}
6364
PIP_TRUSTED_HOST: ${{ vars.PIP_TRUSTED_HOST }}
6465
PIP_EXTRA_INDEX_URL: ${{ vars.PIP_EXTRA_INDEX_URL }}
@@ -147,7 +148,22 @@ jobs:
147148
148149
- name: "Create docker network"
149150
run: |
150-
docker network create -o "com.docker.network.driver.mtu=1500" --ipv6 --subnet 2001:db8::/64 ip6net
151+
# Use ULA prefix (fd00::/8) for proper IPv6 support with NAT
152+
docker network create --ipv6 \
153+
--subnet="fd00:db8::/64" \
154+
-o "com.docker.network.driver.mtu=1500" \
155+
ip6net
156+
157+
# Enable IPv6 forwarding and NAT for internet connectivity
158+
sudo sysctl -w net.ipv6.conf.all.forwarding=1
159+
sudo sysctl -w net.ipv6.conf.default.forwarding=1
160+
161+
# Accept router advertisements even with forwarding enabled
162+
sudo sysctl -w net.ipv6.conf.all.accept_ra=2
163+
sudo sysctl -w net.ipv6.conf.default.accept_ra=2
164+
165+
# Add masquerading for ULA to reach internet (fixes Python 3.11+ IPv6 timeouts)
166+
sudo ip6tables -t nat -A POSTROUTING -s fd00:db8::/64 ! -d fd00:db8::/64 -j MASQUERADE
151167
152168
- name: "Host network config"
153169
run: |
@@ -466,7 +482,22 @@ jobs:
466482
467483
- name: "Create docker network"
468484
run: |
469-
docker network create -o "com.docker.network.driver.mtu=1500" --ipv6 --subnet 2001:db8::/64 ip6net
485+
# Use ULA prefix (fd00::/8) for proper IPv6 support with NAT
486+
docker network create --ipv6 \
487+
--subnet="fd00:db8::/64" \
488+
-o "com.docker.network.driver.mtu=1500" \
489+
ip6net
490+
491+
# Enable IPv6 forwarding and NAT for internet connectivity
492+
sudo sysctl -w net.ipv6.conf.all.forwarding=1
493+
sudo sysctl -w net.ipv6.conf.default.forwarding=1
494+
495+
# Accept router advertisements even with forwarding enabled
496+
sudo sysctl -w net.ipv6.conf.all.accept_ra=2
497+
sudo sysctl -w net.ipv6.conf.default.accept_ra=2
498+
499+
# Add masquerading for ULA to reach internet (fixes Python 3.11+ IPv6 timeouts)
500+
sudo ip6tables -t nat -A POSTROUTING -s fd00:db8::/64 ! -d fd00:db8::/64 -j MASQUERADE
470501
471502
- name: "Host network config"
472503
run: |

salt/_compat.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,4 @@
1414
else:
1515
import salt.ext.ipaddress as ipaddress
1616

17-
if sys.version_info >= (3, 10):
18-
import importlib.metadata as importlib_metadata
19-
else:
20-
# importlib_metadata before version 3.3.0 does not include the functionality we need.
21-
try:
22-
import importlib_metadata
23-
24-
importlib_metadata_version = [
25-
int(part)
26-
for part in importlib_metadata.version("importlib_metadata").split(".")
27-
if part.isdigit()
28-
]
29-
if tuple(importlib_metadata_version) < (3, 3, 0):
30-
# Use the vendored importlib_metadata
31-
import salt.ext.importlib_metadata as importlib_metadata
32-
except ImportError:
33-
# Use the vendored importlib_metadata
34-
import salt.ext.importlib_metadata as importlib_metadata
17+
import importlib.metadata as importlib_metadata

tests/pytests/unit/utils/test_thin.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def __init__(self):
9090
"singledispatch": str(code_dir / "singledispatch.py"),
9191
"looseversion": str(code_dir / "looseversion.py"),
9292
"packaging": str(code_dir / "packaging"),
93+
"backports": str(code_dir / "backports"),
9394
"requests": str(code_dir / "requests"),
9495
"idna": str(code_dir / "idna"),
9596
"urllib3": str(code_dir / "urllib3"),
@@ -1203,6 +1204,7 @@ def test_get_tops_python(thin_ctx):
12031204
(bts(""), bts("")), # backports_abc
12041205
(bts("looseversion.py"), bts("")),
12051206
(bts("packaging/__init__.py"), bts("")),
1207+
(bts("backports/__init__.py"), bts("")), # backports
12061208
(bts("distro.py"), bts("")),
12071209
],
12081210
),
@@ -1251,6 +1253,7 @@ def test_get_tops_python_exclude(thin_ctx):
12511253
(bts(""), bts("")), # backports_abc
12521254
(bts("looseversion.py"), bts("")),
12531255
(bts("packaging/__init__.py"), bts("")),
1256+
(bts("backports/__init__.py"), bts("")), # backports
12541257
(bts("distro.py"), bts("")),
12551258
],
12561259
),
@@ -1301,6 +1304,7 @@ def test_pack_alternatives_exclude(thin_ctx):
13011304
(bts(""), bts("")), # backports_abc
13021305
(bts("looseversion.py"), bts("")),
13031306
(bts("packaging/__init__.py"), bts("")),
1307+
(bts("backports/__init__.py"), bts("")), # backports
13041308
(bts(thin_ctx.fake_libs["distro"]), bts("")),
13051309
],
13061310
),

tests/support/helpers.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,9 +1748,9 @@ def get_installed_packages(self):
17481748
return data
17491749

17501750
def _create_virtualenv(self):
1751-
pyexec = shutil.which("python")
1751+
pyexec = shutil.which("python3") or shutil.which("python")
17521752
if not pyexec:
1753-
pytest.fail("'python' binary not found for virtualenv")
1753+
pytest.fail("'python' or 'python3' binary not found for virtualenv")
17541754
cmd = [
17551755
pyexec,
17561756
"-m",
@@ -1783,14 +1783,29 @@ def _create_virtualenv(self):
17831783
py_version = f"py{sys.version_info.major}.{sys.version_info.minor}"
17841784
self.install(
17851785
"--prefer-binary",
1786-
"-r", code_dir / "requirements" / "static" / "pkg" / py_version / "linux.txt"
1786+
"-r",
1787+
code_dir / "requirements" / "static" / "pkg" / py_version / "linux.txt",
17871788
)
17881789
self.install(RUNTIME_VARS.CODE_DIR)
17891790

17901791
def install(self, *args, **kwargs):
17911792
env = kwargs.pop("env", None) or {}
17921793
env["USE_STATIC_REQUIREMENTS"] = "1"
1794+
# Add relenv toolchain to PATH if it exists
1795+
toolchains_dir = pathlib.Path.home() / ".cache" / "relenv" / "toolchains"
1796+
if toolchains_dir.exists():
1797+
# Find any toolchain subdirectory (e.g., x86_64-linux-gnu, aarch64-linux-gnu)
1798+
for toolchain in toolchains_dir.iterdir():
1799+
if toolchain.is_dir():
1800+
toolchain_bin = toolchain / "bin"
1801+
if toolchain_bin.exists():
1802+
current_path = env.get("PATH", os.environ.get("PATH", ""))
1803+
env["PATH"] = f"{toolchain_bin}:{current_path}"
1804+
break
17931805
kwargs["env"] = env
1806+
# Add --prefer-binary to avoid building from source when possible
1807+
if "--prefer-binary" not in args:
1808+
args = ("--prefer-binary",) + args
17941809
return super().install(*args, **kwargs)
17951810

17961811

0 commit comments

Comments
 (0)