Skip to content

Commit

Permalink
replace test_zypper_dup_works with test_no_downgrade_on_install
Browse files Browse the repository at this point in the history
test_zypper_dup is a bit too agressive and on the other side
misses cases. so we just validate that installing any of the additional
packages would not cause a downgrade in the container.
  • Loading branch information
dirkmueller committed Oct 29, 2023
1 parent 4a8b107 commit 3c99a3d
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 29 deletions.
6 changes: 4 additions & 2 deletions bci_tester/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ def create_BCI(
)


LTSS_VERSIONS = ["15.3"]

LTSS_CONTAINERS = []

if OS_VERSION == "tumbleweed":
Expand All @@ -336,14 +338,14 @@ def create_BCI(
LTSS_CONTAINERS.append(
create_BCI(
build_tag=f"{APP_CONTAINER_PREFIX}/ltss/sle15.3/bci-base:{OS_CONTAINER_TAG}",
available_versions=["15.3"],
available_versions=LTSS_VERSIONS,
bci_type=ImageType.OS_LTSS,
)
)
LTSS_CONTAINERS.append(
create_BCI(
build_tag=f"{APP_CONTAINER_PREFIX}/ltss/sle15.3/bci-base-fips:{OS_CONTAINER_TAG}",
available_versions=["15.3"],
available_versions=LTSS_VERSIONS,
bci_type=ImageType.OS_LTSS,
)
)
Expand Down
99 changes: 72 additions & 27 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"""
import datetime
import fnmatch
import json
import xml.etree.ElementTree as ET

import packaging.version
import pytest
from _pytest.config import Config
from pytest_container import Container
Expand All @@ -13,6 +15,7 @@
from pytest_container import MultiStageBuild
from pytest_container.container import ContainerData

import bci_tester.data as bci
from bci_tester.data import ALL_CONTAINERS
from bci_tester.data import BCI_REPO_NAME
from bci_tester.data import BUSYBOX_CONTAINER
Expand All @@ -23,7 +26,6 @@
from bci_tester.data import OS_VERSION_ID
from bci_tester.data import PCP_CONTAINER
from bci_tester.data import POSTGRESQL_CONTAINERS
from bci_tester.data import TARGET

CONTAINER_IMAGES = ALL_CONTAINERS

Expand Down Expand Up @@ -190,7 +192,63 @@ def test_glibc_present(auto_container):


@pytest.mark.skipif(
TARGET == "ibs-released" and OS_VERSION == "15.3",
OS_VERSION in bci.LTSS_VERSIONS,
reason="LTSS containers are known to be non-functional with BCI_repo ",
)
@pytest.mark.skipif(
OS_VERSION == "basalt",
reason="Basalt repos are known to be out of sync with IBS state",
)
@pytest.mark.parametrize("container", CONTAINERS_WITH_ZYPPER, indirect=True)
def test_no_downgrade_on_install(container: ContainerData) -> None:
"""Check that we can install any additional pacakage in the container.
Check that installing any additional package would not cause a downgrade
of any package already installed in the container as that would throw
a question to the user and break the builds.
"""

conn = container.connection

conn.run_expect([0], "timeout 2m zypper ref")
system_solv = json.loads(
conn.check_output("dumpsolv -j /var/cache/zypp/solv/@System/solv")
)
bci_solv = json.loads(
conn.check_output(
f"dumpsolv -j /var/cache/zypp/solv/{BCI_REPO_NAME}/solv"
)
)
installed_pkgs = {
solvable["solvable:name"]: solvable["solvable:evr"]
for solvable in system_solv["repositories"][0]["solvables"]
}
bci_pkgs = {}
for solvable in bci_solv["repositories"][0]["solvables"]:
bci_pkgs[solvable["solvable:name"]] = solvable["solvable:evr"]
if solvable["solvable:name"] in installed_pkgs:
continue
for req in solvable.get("solvable:requires", ()):
# Skip boolean dependencies or unversioned ones
if "(" in req or " = " not in req:
continue
name, _, version = req.partition(" = ")
if name in installed_pkgs:
installed_version, _, installed_release = installed_pkgs[
name
].partition("-")
version, _, release = version.partition("-")
if installed_version == version and release:
assert packaging.version.parse(
installed_release
) <= packaging.version.parse(release), (
f"Installed {name} = {installed_release} is newer than "
f"what {solvable['solvable:name']} requires (= {release})"
)


@pytest.mark.skipif(
OS_VERSION in bci.LTSS_VERSIONS,
reason="LTSS containers are known to be non-functional with BCI_repo ",
)
@pytest.mark.skipif(
Expand All @@ -200,29 +258,20 @@ def test_glibc_present(auto_container):
@pytest.mark.parametrize(
"container_per_test", CONTAINERS_WITH_ZYPPER, indirect=True
)
def test_zypper_dup_works(container_per_test: ContainerData) -> None:
"""Check that there are no packages installed that we wouldn't find in SLE
BCI repo by running :command:`zypper -n dup` and checking that there are no
conflicts or arch changes and we can update to the state in SLE_BCI repos.
Then validate that SLE_BCI provides all the packages that are afterwards
in the container as well except for the known intentional breakages
(sles-release, skelcd-EULA-bci).
As of 2023-05 the container and the SLE_BCI repositories are released independently
so we frequently get downgrades in this test. allow --allow-downgrade therefore
but still test that there wouldn't be conflicts with what is available in SLE_BCI.
def test_no_orphaned_packages(container_per_test: ContainerData) -> None:
"""Check that containers do not contain any package that isn't also
available via repositories.
"""

container_per_test.connection.run_expect(
[0],
container_per_test.connection.check_output(
f"timeout 5m zypper -n dup --from {BCI_REPO_NAME} -l "
"--no-allow-vendor-change --allow-downgrade --no-allow-arch-change",
"--no-allow-vendor-change --allow-downgrade --no-allow-arch-change"
)

searchresult = ET.fromstring(
container_per_test.connection.run_expect(
[0], "zypper -x -n search -t package -v -i '*'"
).stdout
container_per_test.connection.check_output(
"zypper -x -n search -t package -v -i '*'"
)
)

orphaned_packages = {
Expand All @@ -231,7 +280,6 @@ def test_zypper_dup_works(container_per_test: ContainerData) -> None:
'search-result/solvable-list/solvable[@repository="(System Packages)"]'
)
}

# kubic-locale-archive should be replaced by glibc-locale-base in the containers
# but that is a few bytes larger so we accept it as an exception
known_orphaned_packages = {
Expand All @@ -241,21 +289,18 @@ def test_zypper_dup_works(container_per_test: ContainerData) -> None:
"sles-release",
"ALP-dummy-release",
}

assert not orphaned_packages.difference(known_orphaned_packages)


@pytest.mark.parametrize(
"container_per_test", CONTAINERS_WITH_ZYPPER, indirect=True
)
def test_zypper_verify_passes(container_per_test: ContainerData) -> None:
@pytest.mark.parametrize("container", CONTAINERS_WITH_ZYPPER, indirect=True)
def test_zypper_verify_passes(container: ContainerData) -> None:
"""Check that there are no packages missing according to zypper verify so that
users of the container would not get excessive dependencies installed.
"""
assert (
"Dependencies of all installed packages are satisfied."
in container_per_test.connection.check_output(
"timeout 5m env LC_ALL=C zypper -n verify -D"
in container.connection.check_output(
"timeout 5m env LC_ALL=C zypper --no-refresh -n verify -D"
)
)

Expand Down

0 comments on commit 3c99a3d

Please sign in to comment.