Skip to content

Commit

Permalink
Add architectures and packages selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
dheyay committed Mar 18, 2024
1 parent 57a3956 commit 7b27679
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 20 deletions.
2 changes: 1 addition & 1 deletion uaclient/apt.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ def get_installed_packages() -> List[InstalledAptPackage]:
]


def get_installed_packages_names(include_versions: bool = False) -> List[str]:
def get_installed_packages_names() -> List[str]:
package_list = get_installed_packages()
pkg_names = [pkg.name for pkg in package_list]
return pkg_names
Expand Down
63 changes: 61 additions & 2 deletions uaclient/apt_news.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@

from uaclient import defaults, messages, system, util
from uaclient.api.u.pro.status.is_attached.v1 import _is_attached
from uaclient.apt import ensure_apt_pkg_init
from uaclient.apt import (
ensure_apt_pkg_init,
get_installed_packages,
is_installed,
version_compare,
)
from uaclient.clouds.identity import get_cloud_type
from uaclient.config import UAConfig
from uaclient.contract import ContractExpiryStatus, get_contract_expiry_status
Expand All @@ -31,18 +36,26 @@ class AptNewsMessageSelectors(DataObject):
Field("codenames", data_list(StringDataValue), required=False),
Field("clouds", data_list(StringDataValue), required=False),
Field("pro", BoolDataValue, required=False),
Field("architectures", data_list(StringDataValue), required=False),
Field(
"packages", data_list(data_list(StringDataValue)), required=False
),
]

def __init__(
self,
*,
codenames: Optional[List[str]] = None,
clouds: Optional[List[str]] = None,
pro: Optional[bool] = None
pro: Optional[bool] = None,
architectures: Optional[List[str]] = None,
packages: Optional[List[List[str]]] = None,
):
self.codenames = codenames
self.clouds = clouds
self.pro = pro
self.architectures = architectures
self.packages = packages


class AptNewsMessage(DataObject):
Expand Down Expand Up @@ -88,6 +101,52 @@ def do_selectors_apply(
if selectors.pro != _is_attached(cfg).is_attached:
return False

if selectors.architectures is not None:
if system.get_dpkg_arch() not in selectors.architectures:
return False

if selectors.packages is not None:
installed_packages = get_installed_packages()
installed_packages_names = [
package.name for package in installed_packages
]
package_matched = False

for package in selectors.packages:
if len(package) != 3:
LOG.warning("Invalid package selector: %r", package)
return False

package_name, version_operator, package_version = package
if not is_installed(package_name):
installed_package = installed_packages[
installed_packages_names.index(package_name)
]
version_comparison = version_compare(
installed_package.version, package_version
)
if any(
[
(
version_comparison == 0
and version_operator in ["==", "<=", ">="]
),
(
version_comparison < 0
and version_operator in ["<", "<="]
),
(
version_comparison > 0
and version_operator in [">", ">="]
),
]
):
package_matched = True
break

if not package_matched:
return False

return True


Expand Down
162 changes: 145 additions & 17 deletions uaclient/tests/test_apt_news.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import mock
import pytest

from uaclient import apt_news, messages
from uaclient import apt, apt_news, messages
from uaclient.clouds.identity import NoCloudTypeReason
from uaclient.contract import ContractExpiryStatus

Expand All @@ -13,30 +13,58 @@


class TestAptNews:
# Add architectures and packages
# get list of packages mocked from test_system.py line 591

@pytest.mark.parametrize(
["selectors", "series", "cloud_type", "attached", "expected"],
[
"selectors",
"series",
"cloud_type",
"attached",
"architecture",
"packages",
"expected",
],
[
(
apt_news.AptNewsMessageSelectors(),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
None,
True,
),
(
apt_news.AptNewsMessageSelectors(codenames=["bionic"]),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
None,
False,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic", "xenial"]
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
None,
True,
),
(
apt_news.AptNewsMessageSelectors(codenames=["bionic"]),
apt_news.AptNewsMessageSelectors(
codenames=["xenial"], pro=True
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
None,
False,
),
(
Expand All @@ -45,92 +73,190 @@ class TestAptNews:
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
True,
None,
None,
True,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"],
pro=False,
clouds=["gce"],
),
"bionic",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
None,
False,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["xenial"], pro=True
codenames=["bionic"],
pro=False,
clouds=["gce"],
),
"bionic",
(None, NoCloudTypeReason.CLOUD_ID_ERROR),
False,
None,
None,
False,
),
(
apt_news.AptNewsMessageSelectors(
pro=False, architectures=["amd64"]
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
True,
False,
"amd64",
None,
True,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"], pro=False
pro=False, architectures=["arm64"]
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
"amd64",
None,
False,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"], pro=False
pro=False, packages=[["not-desktop", "==", "1.0.0"]]
),
"bionic",
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
[
apt.InstalledAptPackage(
name="not-desktop", version="1.0.0", arch=""
),
],
True,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"],
pro=False,
clouds=["gce"],
pro=False, packages=[["not-desktop", "=="]]
),
"bionic",
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
[
apt.InstalledAptPackage(
name="not-desktop", version="1.0.0", arch=""
),
],
False,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"],
pro=False,
clouds=["gce"],
pro=False, packages=[["not-desktop", "==", "1.0.0"]]
),
"bionic",
(None, NoCloudTypeReason.CLOUD_ID_ERROR),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
[
apt.InstalledAptPackage(
name="not-desktop", version="1.0.1", arch=""
),
],
False,
),
(
apt_news.AptNewsMessageSelectors(
pro=False, packages=[["not-desktop", ">", "1.0.0"]]
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
[
apt.InstalledAptPackage(
name="not-desktop", version="1.0.1", arch=""
),
],
True,
),
(
apt_news.AptNewsMessageSelectors(
pro=False, packages=[["not-desktop", "<", "1.0.0"]]
),
"xenial",
(None, NoCloudTypeReason.NO_CLOUD_DETECTED),
False,
None,
[
apt.InstalledAptPackage(
name="not-desktop", version="0.0.1", arch=""
),
],
True,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"],
pro=False,
clouds=["gce"],
architectures=["amd64"],
packages=[["not-desktop", ">", "1.0.0"]],
),
"bionic",
("aws", None),
False,
"arm4",
[
apt.InstalledAptPackage(
name="not-desktop", version="0.0.7", arch=""
),
],
False,
),
(
apt_news.AptNewsMessageSelectors(
codenames=["bionic"],
pro=False,
clouds=["gce"],
architectures=["amd64"],
packages=[["not-desktop", ">", "1.0.0"]],
),
"bionic",
("gce", None),
False,
"amd64",
[
apt.InstalledAptPackage(
name="not-desktop", version="1.0.1", arch=""
),
],
True,
),
],
)
@mock.patch(M_PATH + "get_cloud_type")
@mock.patch(M_PATH + "system.get_release_info")
@mock.patch(M_PATH + "system.get_dpkg_arch")
@mock.patch(M_PATH + "get_installed_packages")
def test_do_selectors_apply(
self,
m_installed_packages,
m_get_dpkg_arch,
m_get_platform_info,
m_get_cloud_type,
selectors,
series,
cloud_type,
attached,
architecture,
packages,
expected,
FakeConfig,
):
Expand All @@ -140,6 +266,8 @@ def test_do_selectors_apply(
cfg = FakeConfig()
m_get_platform_info.return_value = mock.MagicMock(series=series)
m_get_cloud_type.return_value = cloud_type
m_get_dpkg_arch.return_value = architecture
m_installed_packages.return_value = packages
assert expected == apt_news.do_selectors_apply(cfg, selectors)

@pytest.mark.parametrize(
Expand Down

0 comments on commit 7b27679

Please sign in to comment.