Add "components" to apt-ostree

Adds support to apt-ostree to manage the Debian packages in logically
separated components. With that, the apt-ostree can manage packages
from different release versions without mixing them.

Changed "add", "list" and "remove" repo commands to have an optional
argument "--component". If passed, the package will be added, list or
removed from the specified component, if not the package will be added,
listed or removed from the default component, created on the apt-ostree
setup with the "--origin" argument (e.g. updates).

Pinned pytest to a specific version to fix py3 job.

Test plan:
PASS Installed apt-ostree from git repo
PASS Run to initialize the repo "apt-ostree repo init \
--feed <feed_dir> --release bookworm --origin updates"

Test plan add:
PASS Download the desired Debian package
PASS Run "apt-ostree repo add --feed <feed_dir> \
--release bookworm --component 24.03.01 <package.deb>"

Test plan list
PASS Run "apt-ostree repo list --feed <feed_dir> \
--release bookworm --component 24.03.01"

Test plan remove:
PASS Run "sudo apt-ostree repo remove --feed <feed_dir> \
--release bookworm --component 24.03.01 <package>"
PASS Run list command to check if the package was removed

Story: 2010867
Task: 50118

Change-Id: I4c6e0df5fccd29e2b3b9a7932932c008f2fe0386
Signed-off-by: Lindley Werner <Lindley.Vieira@windriver.com>
This commit is contained in:
Lindley Werner 2024-05-17 12:33:36 -03:00
parent b06c6eb62e
commit 8022697b60
9 changed files with 79 additions and 25 deletions

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -159,6 +159,21 @@ def release_option(f):
)(f)
def component_option(f):
"""Component option"""
def callback(ctxt, param, value):
state = ctxt.ensure_object(State)
state.component = value
return value
return click.option(
"--component",
help="Component release version (e.g. 24.03.1)",
nargs=1,
required=True,
callback=callback
)(f)
def origin_option(f):
"""Origin option"""
def callback(ctxt, param, value):

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -9,6 +9,7 @@ import sys
import click
from apt_ostree.cmd.options import component_option
from apt_ostree.cmd.options import feed_option
from apt_ostree.cmd.options import packages_option
from apt_ostree.cmd.options import release_option
@ -20,8 +21,9 @@ from apt_ostree.repo import Repo
@pass_state_context
@feed_option
@release_option
@component_option
@packages_option
def add(state, feed, release, packages):
def add(state, feed, release, component, packages):
try:
Repo(state).add()
except KeyboardInterrupt:

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -18,7 +18,7 @@ from apt_ostree.cmd import pass_state_context
from apt_ostree.repo import Repo
@click.command(help="Create a Debian package repsoitory.")
@click.command(help="Create a Debian package repository.")
@pass_state_context
@feed_option
@release_option

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -10,6 +10,7 @@ import sys
import click
from apt_ostree.cmd.options import component_option
from apt_ostree.cmd.options import feed_option
from apt_ostree.cmd.options import release_option
from apt_ostree.cmd import pass_state_context
@ -20,7 +21,8 @@ from apt_ostree.repo import Repo
@pass_state_context
@feed_option
@release_option
def show(state, feed, release):
@component_option
def show(state, feed, release, component):
try:
Repo(state).show()
except KeyboardInterrupt:

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -10,6 +10,7 @@ import sys
import click
from apt_ostree.cmd.options import component_option
from apt_ostree.cmd.options import feed_option
from apt_ostree.cmd.options import packages_option
from apt_ostree.cmd.options import release_option
@ -17,12 +18,13 @@ from apt_ostree.cmd import pass_state_context
from apt_ostree.repo import Repo
@click.command(help="Remove debian package(s) from reposiotry.")
@click.command(help="Remove debian package(s) from repository.")
@pass_state_context
@feed_option
@release_option
@component_option
@packages_option
def remove(state, feed, release, packages):
def remove(state, feed, release, component, packages):
try:
Repo(state).remove()
except KeyboardInterrupt:

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -65,21 +65,33 @@ class Repo:
)
def add(self):
"""Add Debian package(s) to repository."""
"""Add Debian package(s) to a component."""
config = self.repo.joinpath("conf/distributions")
component = self.state.component or self.state.origin
utils.check_and_append_component(config, component)
for pkg in self.state.packages:
self.logging.info(f"Adding {pkg}.")
self.logging.info(
f"Adding {pkg} to component {component}.")
r = utils.run_command(
["reprepro", "-b", str(self.repo), "includedeb",
self.state.release, pkg])
["reprepro", "-b", str(self.repo), "-C", component,
"includedeb", self.state.release, pkg])
if r.returncode == 0:
self.logging.info(f"Successfully added {pkg}\n")
self.logging.info(
f"Successfully added {pkg} to component {component}\n")
else:
self.logging.error(f"Failed to add {pkg}\n")
self.logging.error(
f"Failed to add {pkg} to component {component}\n")
def show(self):
"""Display a table of packages in the archive."""
component = self.state.component or self.state.origin
r = utils.run_command(
["reprepro", "-b", str(self.repo), "list", self.state.release],
["reprepro", "-b", str(self.repo),
"-C", component,
"list", self.state.release],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=False,
@ -107,17 +119,21 @@ class Repo:
self.console.print(table)
def remove(self):
"""Remove a Debian package from an archive."""
"""Remove a Debian package from a component."""
component = self.state.component or self.state.origin
for pkg in self.state.packages:
self.logging.info(f"Removing {pkg}.")
r = utils.run_command(
["reprepro", "-b", str(self.repo), "remove",
self.state.release, pkg],
["reprepro", "-b", str(self.repo), "-C", component,
"remove", self.state.release, pkg],
check=True)
if r.returncode == 0:
self.logging.info(f"Successfully removed {pkg}\n")
self.logging.info(
f"Successfully removed {pkg} from component {component}\n")
else:
self.logging.error(f"Failed to remove {pkg}\n")
self.logging.error(
f"Failed to remove {pkg} from component {component}\n")
def disable_repo(self):
"""Disable Debian feed via apt-add-repository."""

View File

@ -1,5 +1,5 @@
"""
Copyright (c) 2023 Wind River Systems, Inc.
Copyright (c) 2023-2024 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0
@ -85,3 +85,18 @@ def run_sandbox_command(
check=check,
env=env,
)
def check_and_append_component(config_path, component):
with open(config_path, 'r') as file:
lines = file.readlines()
for i, line in enumerate(lines):
if line.startswith("Components:"):
components = line.split()[1:]
if component not in components:
lines[i] = line.strip() + f" {component}\n"
break
with open(config_path, 'w') as file:
file.writelines(lines)

View File

@ -10,7 +10,7 @@ oslotest>=3.8.0 # Apache-2.0
testresources>=2.0.0 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=2.5.0 # MIT
pytest
pytest<=8.1.1
pylint
yamllint<1.26.4 # GPLv3
doc8

View File

@ -17,6 +17,8 @@ setenv =
deps =
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
allowlist_externals =
pytest
commands = pytest -rx -v ./apt_ostree/tests
[testenv:lower-constraints]