mirror: allow to combine different filters for the candidates
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
parent
1350ef8d1b
commit
10a2e6ac22
|
@ -75,7 +75,10 @@ import abc
|
||||||
import copy
|
import copy
|
||||||
import contextlib
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Iterator, List, Optional, Sequence, Set, Union
|
from typing import (
|
||||||
|
Any, Callable, Dict, Iterator, List,
|
||||||
|
Optional, Sequence, Set, Union,
|
||||||
|
)
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -130,6 +133,11 @@ class BasePrimaryEntry(abc.ABC):
|
||||||
def serialize_for_ai(self) -> Any:
|
def serialize_for_ai(self) -> Any:
|
||||||
""" Serialize the entry for autoinstall. """
|
""" Serialize the entry for autoinstall. """
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def supports_arch(self, arch: str) -> bool:
|
||||||
|
""" Tells whether the mirror claims to support the architecture
|
||||||
|
specified. """
|
||||||
|
|
||||||
|
|
||||||
@attr.s(auto_attribs=True)
|
@attr.s(auto_attribs=True)
|
||||||
class PrimaryEntry(BasePrimaryEntry):
|
class PrimaryEntry(BasePrimaryEntry):
|
||||||
|
@ -159,8 +167,6 @@ class PrimaryEntry(BasePrimaryEntry):
|
||||||
return [{"uri": self.uri, "arches": ["default"]}]
|
return [{"uri": self.uri, "arches": ["default"]}]
|
||||||
|
|
||||||
def supports_arch(self, arch: str) -> bool:
|
def supports_arch(self, arch: str) -> bool:
|
||||||
""" Tells whether the mirror claims to support the architecture
|
|
||||||
specified. """
|
|
||||||
if self.arches is None:
|
if self.arches is None:
|
||||||
return True
|
return True
|
||||||
return arch in self.arches
|
return arch in self.arches
|
||||||
|
@ -207,6 +213,11 @@ class LegacyPrimaryEntry(BasePrimaryEntry):
|
||||||
def serialize_for_ai(self) -> List[Any]:
|
def serialize_for_ai(self) -> List[Any]:
|
||||||
return self.config
|
return self.config
|
||||||
|
|
||||||
|
def supports_arch(self, arch: str) -> bool:
|
||||||
|
# Curtin will always find a mirror ; albeit with the ["default"]
|
||||||
|
# architectures.
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def countrify_uri(uri: str, cc: str) -> str:
|
def countrify_uri(uri: str, cc: str) -> str:
|
||||||
""" Return a URL where the host is prefixed with a country code. """
|
""" Return a URL where the host is prefixed with a country code. """
|
||||||
|
@ -215,6 +226,18 @@ def countrify_uri(uri: str, cc: str) -> str:
|
||||||
return parse.urlunparse(new)
|
return parse.urlunparse(new)
|
||||||
|
|
||||||
|
|
||||||
|
CandidateFilter = Callable[[BasePrimaryEntry], bool]
|
||||||
|
|
||||||
|
|
||||||
|
def filter_candidates(candidates: List[BasePrimaryEntry],
|
||||||
|
*, filters: Sequence[CandidateFilter]) \
|
||||||
|
-> Iterator[BasePrimaryEntry]:
|
||||||
|
candidates_iter = iter(candidates)
|
||||||
|
for filt in filters:
|
||||||
|
candidates_iter = filter(filt, candidates_iter)
|
||||||
|
return candidates_iter
|
||||||
|
|
||||||
|
|
||||||
class MirrorModel(object):
|
class MirrorModel(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -312,8 +335,12 @@ class MirrorModel(object):
|
||||||
# install. It will be placed in etc/apt/sources.list of the target
|
# install. It will be placed in etc/apt/sources.list of the target
|
||||||
# system.
|
# system.
|
||||||
with contextlib.suppress(StopIteration):
|
with contextlib.suppress(StopIteration):
|
||||||
candidate = next(filter(lambda c: c.uri is not None,
|
filters = [
|
||||||
self.compatible_primary_candidates()))
|
lambda c: c.uri is not None,
|
||||||
|
lambda c: c.supports_arch(self.architecture),
|
||||||
|
]
|
||||||
|
candidate = next(filter_candidates(self.primary_candidates,
|
||||||
|
filters=filters))
|
||||||
return self._get_apt_config_using_candidate(candidate)
|
return self._get_apt_config_using_candidate(candidate)
|
||||||
# Our last resort is to include no primary section. Curtin will use
|
# Our last resort is to include no primary section. Curtin will use
|
||||||
# its own internal values.
|
# its own internal values.
|
||||||
|
@ -357,20 +384,20 @@ class MirrorModel(object):
|
||||||
return next(self.country_mirror_candidates(), None) is not None
|
return next(self.country_mirror_candidates(), None) is not None
|
||||||
|
|
||||||
def country_mirror_candidates(self) -> Iterator[BasePrimaryEntry]:
|
def country_mirror_candidates(self) -> Iterator[BasePrimaryEntry]:
|
||||||
for candidate in self.primary_candidates:
|
def filt(candidate):
|
||||||
if self.legacy_primary and candidate.mirror_is_default():
|
if self.legacy_primary and candidate.mirror_is_default():
|
||||||
yield candidate
|
return True
|
||||||
elif not self.legacy_primary and candidate.country_mirror:
|
elif not self.legacy_primary and candidate.country_mirror:
|
||||||
yield candidate
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
return filter_candidates(self.primary_candidates, filters=[filt])
|
||||||
|
|
||||||
def compatible_primary_candidates(self) -> Iterator[BasePrimaryEntry]:
|
def compatible_primary_candidates(self) -> Iterator[BasePrimaryEntry]:
|
||||||
for candidate in self.primary_candidates:
|
def filt(candidate):
|
||||||
if self.legacy_primary:
|
return candidate.supports_arch(self.architecture)
|
||||||
yield candidate
|
|
||||||
elif candidate.arches is None:
|
return filter_candidates(self.primary_candidates, filters=[filt])
|
||||||
yield candidate
|
|
||||||
elif self.architecture in candidate.arches:
|
|
||||||
yield candidate
|
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
return {}
|
return {}
|
||||||
|
|
Loading…
Reference in New Issue