mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-23 23:07:17 +00:00
parent
9964a96296
commit
046febc440
51
Dockerfile
Normal file
51
Dockerfile
Normal file
@ -0,0 +1,51 @@
|
||||
FROM archlinux:base-devel
|
||||
|
||||
# image configuration
|
||||
ENV AHRIMAN_ARCHITECTURE="x86_64"
|
||||
ENV AHRIMAN_DEBUG=""
|
||||
ENV AHRIMAN_FORCE_ROOT=""
|
||||
ENV AHRIMAN_OUTPUT="syslog"
|
||||
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
||||
ENV AHRIMAN_PORT=""
|
||||
ENV AHRIMAN_REPOSITORY="aur-clone"
|
||||
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
|
||||
ENV AHRIMAN_USER="ahriman"
|
||||
|
||||
# install environment
|
||||
## install git which is required for AUR interaction and go for yay
|
||||
RUN pacman --noconfirm -Syu git go
|
||||
## create build user
|
||||
RUN useradd -m -d /home/build -s /usr/bin/nologin build && \
|
||||
echo "build ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/build
|
||||
## install AUR helper
|
||||
RUN YAY_DIR="$(runuser -u build -- mktemp -d)" && \
|
||||
git clone https://aur.archlinux.org/yay.git "$YAY_DIR" && \
|
||||
cd "$YAY_DIR" && \
|
||||
runuser -u build -- makepkg --noconfirm --install && \
|
||||
cd - && rm -r "$YAY_DIR"
|
||||
## install package dependencies
|
||||
RUN runuser -u build -- yay --noconfirm -Sy devtools git pyalpm python-inflection python-passlib python-srcinfo && \
|
||||
runuser -u build -- yay --noconfirm -Sy python-pip && \
|
||||
runuser -u build -- yay --noconfirm -Sy breezy darcs mercurial python-aioauth-client python-aiohttp \
|
||||
python-aiohttp-debugtoolbar python-aiohttp-jinja2 python-aiohttp-security \
|
||||
python-aiohttp-session python-boto3 python-cryptography python-jinja \
|
||||
rsync subversion
|
||||
|
||||
# install ahriman
|
||||
## copy tree
|
||||
COPY --chown=build . "/home/build/ahriman"
|
||||
## create package archive and install it
|
||||
RUN cd /home/build/ahriman && \
|
||||
make VERSION="$(git describe --tags --abbrev=0)" archlinux && \
|
||||
cp ./*-src.tar.xz package/archlinux && \
|
||||
cd package/archlinux && \
|
||||
runuser -u build -- makepkg --noconfirm --install --skipchecksums && \
|
||||
cd - && rm -r /home/build/ahriman
|
||||
|
||||
VOLUME ["/var/lib/ahriman"]
|
||||
|
||||
# minimal runtime ahriman setup
|
||||
COPY "docker/entrypoint.sh" "/usr/local/bin/entrypoint"
|
||||
ENTRYPOINT ["entrypoint"]
|
||||
# default command
|
||||
CMD ["repo-update"]
|
50
docker/entrypoint.sh
Executable file
50
docker/entrypoint.sh
Executable file
@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
[ -n "$AHRIMAN_DEBUG" ] && set -x
|
||||
|
||||
# configuration tune
|
||||
sed -i "s|root = /var/lib/ahriman|root = $AHRIMAN_REPOSITORY_ROOT|g" "/etc/ahriman.ini"
|
||||
sed -i "s|host = 127.0.0.1|host = 0.0.0.0|g" "/etc/ahriman.ini"
|
||||
sed -i "s|handlers = syslog_handler|handlers = ${AHRIMAN_OUTPUT}_handler|g" "/etc/ahriman.ini.d/logging.ini"
|
||||
|
||||
AHRIMAN_DEFAULT_ARGS=("-a" "$AHRIMAN_ARCHITECTURE")
|
||||
if [[ "$AHRIMAN_OUTPUT" == "syslog" ]]; then
|
||||
if [ ! -e "/dev/log" ]; then
|
||||
# by default ahriman uses syslog which is not available inside container
|
||||
# to make noise less we force quiet mode in case if /dev/log was not mounted
|
||||
AHRIMAN_DEFAULT_ARGS+=("-q")
|
||||
fi
|
||||
fi
|
||||
|
||||
# create repository root inside the [[mounted]] directory and set correct ownership
|
||||
[ -d "$AHRIMAN_REPOSITORY_ROOT" ] || mkdir "$AHRIMAN_REPOSITORY_ROOT"
|
||||
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_REPOSITORY_ROOT"
|
||||
# run initial setup
|
||||
sudo -u "$AHRIMAN_USER" -- ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" repo-init
|
||||
|
||||
# run built-in setup command
|
||||
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
|
||||
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
|
||||
AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
|
||||
if [ -n "$AHRIMAN_PORT" ]; then
|
||||
# in addition it must be handled in docker run command
|
||||
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
|
||||
fi
|
||||
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" repo-setup "${AHRIMAN_SETUP_ARGS[@]}"
|
||||
|
||||
# refresh database
|
||||
runuser -u build -- yay --noconfirm -Syy &> /dev/null
|
||||
# create machine-id which is required by build tools
|
||||
systemd-machine-id-setup &> /dev/null
|
||||
|
||||
# if AHRIMAN_FORCE_ROOT is set or command is unsafe we can run without sudo
|
||||
# otherwise we prepend executable by sudo command
|
||||
if [ -n "$AHRIMAN_FORCE_ROOT" ]; then
|
||||
AHRIMAN_EXECUTABLE=("ahriman")
|
||||
elif ahriman help-commands-unsafe | grep -Fxq "$1"; then
|
||||
AHRIMAN_EXECUTABLE=("ahriman")
|
||||
else
|
||||
AHRIMAN_EXECUTABLE=("sudo" "-u" "$AHRIMAN_USER" "--" "ahriman")
|
||||
fi
|
||||
exec "${AHRIMAN_EXECUTABLE[@]}" "${AHRIMAN_DEFAULT_ARGS[@]}" "$@"
|
60
docs/faq.md
60
docs/faq.md
@ -198,6 +198,66 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
## Docker image
|
||||
|
||||
We provide official images which can be found under `arcan1s/ahriman` repository. Docker image is being updated on each master commit as well as on each version. If you would like to use last (probably unstable build) you can use `latest` tag; otherwise you can use any version tag available.
|
||||
|
||||
The default action (in case if no arguments provided) is `repo-update`. Basically the idea is to run container, e.g.:
|
||||
|
||||
```shell
|
||||
docker run --privileged -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
```
|
||||
|
||||
`--privileged` flag is required to make mount possible inside container. In addition, you can pass own configuration overrides by using the same `-v` flag, e.g.:
|
||||
|
||||
```shell
|
||||
docker run -v /path/to/local/repo:/var/lib/ahriman -v /etc/ahriman.ini:/etc/ahriman.ini.d/10-overrides.ini arcan1s/ahriman:latest
|
||||
```
|
||||
|
||||
By default, it runs `repo-update`, but it can be overwritten to any other command you would like to, e.g.:
|
||||
|
||||
```shell
|
||||
docker run arcan1s/ahriman:latest package-add ahriman --now
|
||||
```
|
||||
|
||||
For more details please refer to docker FAQ.
|
||||
|
||||
### Environment variables
|
||||
|
||||
The following environment variables are supported:
|
||||
|
||||
* `AHRIMAN_ARCHITECTURE` - architecture of the repository, default is `x86_64`.
|
||||
* `AHRIMAN_DEBUG` - if set all commands will be logged to console.
|
||||
* `AHRIMAN_FORCE_ROOT` - force run ahriman as root instead of guessing by subcommand.
|
||||
* `AHRIMAN_OUTPUT` - controls logging handler, e.g. `syslog`, `console`. The name must be found in logging configuration. Note that if `syslog` (the default) handler is used you will need to mount `/dev/log` inside container because it is not available there.
|
||||
* `AHRIMAN_PACKAGER` - packager name from which packages will be built, default is `ahriman bot <ahriman@example.com>`.
|
||||
* `AHRIMAN_PORT` - HTTP server port if any, default is empty.
|
||||
* `AHRIMAN_REPOSITORY` - repository name, default is `aur-clone`.
|
||||
* `AHRIMAN_REPOSITORY_ROOT` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses `ahriman` directory inside ahriman's home, which can be passed as mount volume.
|
||||
* `AHRIMAN_USER` - ahriman user, usually must not be overwritten, default is `ahriman`.
|
||||
|
||||
You can pass any of these variables by using `-e` argument, e.g.:
|
||||
|
||||
```shell
|
||||
docker run -e AHRIMAN_PORT=8080 arcan1s/ahriman:latest
|
||||
```
|
||||
|
||||
### Working with web service
|
||||
|
||||
Well for that you would need to have web container instance running forever; it can be achieved by the following command:
|
||||
|
||||
```shell
|
||||
docker run -p 8080:8080 -e AHRIMAN_PORT=8080 -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
```
|
||||
|
||||
Note about `AHRIMAN_PORT` environment variable which is required in order to enable web service. An additional port bind by `-p 8080:8080` is required to pass docker port outside of container.
|
||||
|
||||
For every next container run use arguments `-e AHRIMAN_PORT=8080 --net=host`, e.g.:
|
||||
|
||||
```shell
|
||||
docker run --privileged -e AHRIMAN_PORT=8080 --net=host -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
```
|
||||
|
||||
## Remote synchronization
|
||||
|
||||
### Wait I would like to use the repository from another server
|
||||
|
@ -72,6 +72,7 @@ def _parser() -> argparse.ArgumentParser:
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
|
||||
|
||||
_set_aur_search_parser(subparsers)
|
||||
_set_help_commands_unsafe(subparsers)
|
||||
_set_key_import_parser(subparsers)
|
||||
_set_package_add_parser(subparsers)
|
||||
_set_package_remove_parser(subparsers)
|
||||
@ -118,6 +119,19 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def _set_help_commands_unsafe(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing unsafe commands
|
||||
:param root: subparsers for the commands
|
||||
:return: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
|
||||
description="list unsafe commands as defined in default args", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, no_report=True, quiet=True,
|
||||
unsafe=True, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for key import subcommand
|
||||
@ -396,6 +410,7 @@ def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="create initial service configuration, requires root",
|
||||
epilog="Create _minimal_ configuration for the service according to provided options.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||
parser.add_argument("--build-command", help="build command prefix", default="ahriman")
|
||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||
type=Path, default=Path("/usr/share/devtools/pacman-extra.conf"))
|
||||
|
@ -32,14 +32,15 @@ class Properties:
|
||||
:ivar repository: repository instance
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, no_report: bool) -> None:
|
||||
def __init__(self, architecture: str, configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.configuration = configuration
|
||||
self.architecture = architecture
|
||||
self.repository = Repository(architecture, configuration, no_report)
|
||||
self.repository = Repository(architecture, configuration, no_report, unsafe)
|
||||
|
@ -35,6 +35,7 @@ from ahriman.application.handlers.sign import Sign
|
||||
from ahriman.application.handlers.status import Status
|
||||
from ahriman.application.handlers.status_update import StatusUpdate
|
||||
from ahriman.application.handlers.sync import Sync
|
||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||
from ahriman.application.handlers.update import Update
|
||||
from ahriman.application.handlers.user import User
|
||||
from ahriman.application.handlers.web import Web
|
||||
|
@ -33,15 +33,16 @@ class Add(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
application.add(args.package, args.source, args.without_dependencies)
|
||||
if not args.now:
|
||||
return
|
||||
|
@ -33,13 +33,14 @@ class Clean(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).clean(
|
||||
Application(architecture, configuration, no_report, unsafe).clean(
|
||||
args.build, args.cache, args.chroot, args.manual, args.packages, args.patches)
|
||||
|
@ -35,13 +35,14 @@ class Dump(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
dump = configuration.dump()
|
||||
for section, values in sorted(dump.items()):
|
||||
|
@ -76,7 +76,7 @@ class Handler:
|
||||
try:
|
||||
configuration = Configuration.from_path(args.configuration, architecture, args.quiet)
|
||||
with Lock(args, architecture, configuration):
|
||||
cls.run(args, architecture, configuration, args.no_report)
|
||||
cls.run(args, architecture, configuration, args.no_report, args.unsafe)
|
||||
return True
|
||||
except Exception:
|
||||
# we are basically always want to print error to stderr instead of default logger
|
||||
@ -107,12 +107,13 @@ class Handler:
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
@ -35,12 +35,13 @@ class Init(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).repository.repo.init()
|
||||
Application(architecture, configuration, no_report, unsafe).repository.repo.init()
|
||||
|
@ -35,12 +35,14 @@ class KeyImport(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).repository.sign.key_import(args.key_server, args.key)
|
||||
Application(architecture, configuration, no_report, unsafe).repository.sign.key_import(
|
||||
args.key_server, args.key)
|
||||
|
@ -41,15 +41,16 @@ class Patch(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
|
||||
if args.action == Action.List:
|
||||
Patch.patch_set_list(application, args.package)
|
||||
|
@ -34,17 +34,18 @@ class Rebuild(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
depends_on = set(args.depends_on) if args.depends_on else None
|
||||
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
updates = application.repository.packages_depends_on(depends_on)
|
||||
if args.dry_run:
|
||||
for package in updates:
|
||||
|
@ -33,12 +33,13 @@ class Remove(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).remove(args.package)
|
||||
Application(architecture, configuration, no_report, unsafe).remove(args.package)
|
||||
|
@ -34,15 +34,16 @@ class RemoveUnknown(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
unknown_packages = application.unknown()
|
||||
if args.dry_run:
|
||||
for package in sorted(unknown_packages):
|
||||
|
@ -33,12 +33,13 @@ class Report(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).report(args.target, [])
|
||||
Application(architecture, configuration, no_report, unsafe).report(args.target, [])
|
||||
|
@ -42,13 +42,14 @@ class Search(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
packages_list = AUR.multisearch(*args.search)
|
||||
for package in Search.sort(packages_list, args.sort_by):
|
||||
|
@ -46,15 +46,16 @@ class Setup(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
Setup.configuration_create_makepkg(args.packager, application.repository.paths)
|
||||
Setup.executable_create(args.build_command, architecture)
|
||||
Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration,
|
||||
@ -87,6 +88,8 @@ class Setup(Handler):
|
||||
section = Configuration.section_name("build", architecture)
|
||||
configuration.set_option(section, "build_command", str(Setup.build_command(args.build_command, architecture)))
|
||||
configuration.set_option("repository", "name", repository)
|
||||
if args.build_as_user is not None:
|
||||
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")
|
||||
|
||||
if args.sign_key is not None:
|
||||
section = Configuration.section_name("sign", architecture)
|
||||
|
@ -33,12 +33,13 @@ class Sign(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).sign(args.package)
|
||||
Application(architecture, configuration, no_report, unsafe).sign(args.package)
|
||||
|
@ -39,16 +39,17 @@ class Status(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
# we are using reporter here
|
||||
client = Application(architecture, configuration, no_report=False).repository.reporter
|
||||
client = Application(architecture, configuration, no_report=False, unsafe=unsafe).repository.reporter
|
||||
if args.ahriman:
|
||||
ahriman = client.get_self()
|
||||
StatusPrinter(ahriman).print(args.info)
|
||||
|
@ -36,16 +36,17 @@ class StatusUpdate(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
# we are using reporter here
|
||||
client = Application(architecture, configuration, no_report=False).repository.reporter
|
||||
client = Application(architecture, configuration, no_report=False, unsafe=unsafe).repository.reporter
|
||||
|
||||
if args.action == Action.Update and args.package:
|
||||
# update packages statuses
|
||||
|
@ -33,12 +33,13 @@ class Sync(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
Application(architecture, configuration, no_report).sync(args.target, [])
|
||||
Application(architecture, configuration, no_report, unsafe).sync(args.target, [])
|
||||
|
58
src/ahriman/application/handlers/unsafe_commands.py
Normal file
58
src/ahriman/application/handlers/unsafe_commands.py
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# Copyright (c) 2021 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.formatters.string_printer import StringPrinter
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
class UnsafeCommands(Handler):
|
||||
"""
|
||||
unsafe command help parser
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
unsafe_commands = UnsafeCommands.get_unsafe_commands(args.parser())
|
||||
for command in unsafe_commands:
|
||||
StringPrinter(command).print(verbose=True)
|
||||
|
||||
@staticmethod
|
||||
def get_unsafe_commands(parser: argparse.ArgumentParser) -> List[str]:
|
||||
"""
|
||||
extract unsafe commands from argument parser
|
||||
:param parser: generated argument parser
|
||||
:return: list of commands with default unsafe flag
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))
|
||||
return [action_name for action_name, action in subparser.choices.items() if action.get_default("unsafe")]
|
@ -33,15 +33,16 @@ class Update(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, no_report)
|
||||
application = Application(architecture, configuration, no_report, unsafe)
|
||||
packages = application.updates(args.package, args.no_aur, args.no_local, args.no_manual, args.no_vcs,
|
||||
Update.log_fn(application, args.dry_run))
|
||||
if args.dry_run:
|
||||
|
@ -40,13 +40,14 @@ class User(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
salt = User.get_salt(configuration)
|
||||
user = User.user_create(args)
|
||||
@ -58,7 +59,7 @@ class User(Handler):
|
||||
User.configuration_write(auth_configuration, args.secure)
|
||||
|
||||
if not args.no_reload:
|
||||
client = Application(architecture, configuration, no_report=False).repository.reporter
|
||||
client = Application(architecture, configuration, no_report=False, unsafe=unsafe).repository.reporter
|
||||
client.reload_auth()
|
||||
|
||||
@staticmethod
|
||||
|
@ -36,13 +36,14 @@ class Web(Handler):
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration, no_report: bool) -> None:
|
||||
configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
:param args: command line args
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
# we are using local import for optional dependencies
|
||||
from ahriman.web.web import run_server, setup_service
|
||||
|
@ -103,9 +103,7 @@ class Lock:
|
||||
"""
|
||||
check if current user is actually owner of ahriman root
|
||||
"""
|
||||
if self.unsafe:
|
||||
return
|
||||
check_user(self.root)
|
||||
check_user(self.root, self.unsafe)
|
||||
|
||||
def clear(self) -> None:
|
||||
"""
|
||||
|
@ -45,12 +45,13 @@ class Properties:
|
||||
:ivar sign: GPG wrapper instance
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, no_report: bool) -> None:
|
||||
def __init__(self, architecture: str, configuration: Configuration, no_report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param no_report: force disable reporting
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
@ -61,7 +62,7 @@ class Properties:
|
||||
|
||||
self.paths = RepositoryPaths(configuration.getpath("repository", "root"), architecture)
|
||||
try:
|
||||
check_user(self.paths.root)
|
||||
check_user(self.paths.root, unsafe)
|
||||
self.paths.tree_create()
|
||||
except UnsafeRun:
|
||||
self.logger.warning("root owner differs from the current user, skipping tree creation")
|
||||
|
@ -49,7 +49,7 @@ class Watcher:
|
||||
self.logger = logging.getLogger("http")
|
||||
|
||||
self.architecture = architecture
|
||||
self.repository = Repository(architecture, configuration, no_report=True)
|
||||
self.repository = Repository(architecture, configuration, no_report=True, unsafe=False)
|
||||
|
||||
self.known: Dict[str, Tuple[Package, BuildStatus]] = {}
|
||||
self.status = BuildStatus()
|
||||
|
@ -55,13 +55,16 @@ def check_output(*args: str, exception: Optional[Exception], cwd: Optional[Path]
|
||||
raise exception or e
|
||||
|
||||
|
||||
def check_user(root: Path) -> None:
|
||||
def check_user(root: Path, unsafe: bool) -> None:
|
||||
"""
|
||||
check if current user is the owner of the root
|
||||
:param root: root directory (i.e. ahriman home)
|
||||
:param unsafe: if set no user check will be performed before path creation
|
||||
"""
|
||||
if not root.exists():
|
||||
return # no directory found, skip check
|
||||
if unsafe:
|
||||
return # unsafe flag is enabled, no check performed
|
||||
current_uid = os.getuid()
|
||||
root_uid = root.stat().st_uid
|
||||
if current_uid != root_uid:
|
||||
|
@ -17,7 +17,7 @@ def application_packages(configuration: Configuration, mocker: MockerFixture) ->
|
||||
:return: application test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Packages("x86_64", configuration, no_report=True)
|
||||
return Packages("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -29,7 +29,7 @@ def application_properties(configuration: Configuration, mocker: MockerFixture)
|
||||
:return: application test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Properties("x86_64", configuration, no_report=True)
|
||||
return Properties("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -41,4 +41,4 @@ def application_repository(configuration: Configuration, mocker: MockerFixture)
|
||||
:return: application test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Repository("x86_64", configuration, no_report=True)
|
||||
return Repository("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
@ -18,7 +18,7 @@ def application(configuration: Configuration, mocker: MockerFixture) -> Applicat
|
||||
:return: application test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Application("x86_64", configuration, no_report=True)
|
||||
return Application("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -114,4 +114,4 @@ def test_run(args: argparse.Namespace, configuration: Configuration) -> None:
|
||||
must raise NotImplemented for missing method
|
||||
"""
|
||||
with pytest.raises(NotImplementedError):
|
||||
Handler.run(args, "x86_64", configuration, True)
|
||||
Handler.run(args, "x86_64", configuration, True, True)
|
||||
|
@ -30,7 +30,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.add")
|
||||
|
||||
Add.run(args, "x86_64", configuration, True)
|
||||
Add.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(args.package, args.source, args.without_dependencies)
|
||||
|
||||
|
||||
@ -46,6 +46,6 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
|
||||
|
||||
Add.run(args, "x86_64", configuration, True)
|
||||
Add.run(args, "x86_64", configuration, True, False)
|
||||
updates_mock.assert_called_once_with(args.package, True, True, False, True, pytest.helpers.anyvar(int))
|
||||
application_mock.assert_called_once_with([package_ahriman])
|
||||
|
@ -29,5 +29,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.clean")
|
||||
|
||||
Clean.run(args, "x86_64", configuration, True)
|
||||
Clean.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(False, False, False, False, False, False)
|
||||
|
@ -15,7 +15,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
|
||||
return_value=configuration.dump())
|
||||
|
||||
Dump.run(args, "x86_64", configuration, True)
|
||||
Dump.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with()
|
||||
print_mock.assert_called()
|
||||
|
||||
|
@ -14,7 +14,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
|
||||
|
||||
Init.run(args, "x86_64", configuration, True)
|
||||
Init.run(args, "x86_64", configuration, True, False)
|
||||
tree_create_mock.assert_called_once_with()
|
||||
init_mock.assert_called_once_with()
|
||||
|
||||
|
@ -25,7 +25,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.key_import")
|
||||
|
||||
KeyImport.run(args, "x86_64", configuration, True)
|
||||
KeyImport.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(args.key_server, args.key)
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_create")
|
||||
|
||||
Patch.run(args, "x86_64", configuration, True)
|
||||
Patch.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, args.track)
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, mocker
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_list")
|
||||
|
||||
Patch.run(args, "x86_64", configuration, True)
|
||||
Patch.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package)
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, mock
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_remove")
|
||||
|
||||
Patch.run(args, "x86_64", configuration, True)
|
||||
Patch.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package)
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ def test_run(args: argparse.Namespace, package_ahriman: Package,
|
||||
return_value=[package_ahriman])
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
|
||||
Rebuild.run(args, "x86_64", configuration, True)
|
||||
Rebuild.run(args, "x86_64", configuration, True, False)
|
||||
application_packages_mock.assert_called_once_with(None)
|
||||
application_mock.assert_called_once_with([package_ahriman])
|
||||
|
||||
@ -45,7 +45,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration,
|
||||
mocker.patch("ahriman.core.repository.repository.Repository.packages_depends_on", return_value=[package_ahriman])
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
|
||||
Rebuild.run(args, "x86_64", configuration, True)
|
||||
Rebuild.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_not_called()
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ def test_run_filter(args: argparse.Namespace, configuration: Configuration, mock
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depends_on")
|
||||
|
||||
Rebuild.run(args, "x86_64", configuration, True)
|
||||
Rebuild.run(args, "x86_64", configuration, True, False)
|
||||
application_packages_mock.assert_called_once_with({"python-aur"})
|
||||
|
||||
|
||||
@ -72,5 +72,5 @@ def test_run_without_filter(args: argparse.Namespace, configuration: Configurati
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depends_on")
|
||||
|
||||
Rebuild.run(args, "x86_64", configuration, True)
|
||||
Rebuild.run(args, "x86_64", configuration, True, False)
|
||||
application_packages_mock.assert_called_once_with(None)
|
||||
|
@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
|
||||
Remove.run(args, "x86_64", configuration, True)
|
||||
Remove.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with([])
|
||||
|
@ -29,7 +29,7 @@ def test_run(args: argparse.Namespace, package_ahriman: Package,
|
||||
return_value=[package_ahriman])
|
||||
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True)
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with()
|
||||
remove_mock.assert_called_once_with([package_ahriman])
|
||||
|
||||
@ -47,7 +47,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, pac
|
||||
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True)
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with()
|
||||
remove_mock.assert_not_called()
|
||||
print_mock.assert_called_once_with(False)
|
||||
@ -67,7 +67,7 @@ def test_run_dry_run_verbose(args: argparse.Namespace, configuration: Configurat
|
||||
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True)
|
||||
RemoveUnknown.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with()
|
||||
remove_mock.assert_not_called()
|
||||
print_mock.assert_called_once_with(True)
|
||||
|
@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.report")
|
||||
|
||||
Report.run(args, "x86_64", configuration, True)
|
||||
Report.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(args.target, [])
|
||||
|
@ -31,7 +31,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, aur_package
|
||||
search_mock = mocker.patch("ahriman.core.alpm.aur.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
Search.run(args, "x86_64", configuration, True)
|
||||
Search.run(args, "x86_64", configuration, True, False)
|
||||
search_mock.assert_called_once_with("ahriman")
|
||||
print_mock.assert_called_once_with(False)
|
||||
|
||||
@ -45,7 +45,7 @@ def test_run_sort(args: argparse.Namespace, configuration: Configuration, aur_pa
|
||||
mocker.patch("ahriman.core.alpm.aur.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
|
||||
|
||||
Search.run(args, "x86_64", configuration, True)
|
||||
Search.run(args, "x86_64", configuration, True, False)
|
||||
sort_mock.assert_called_once_with([aur_package_ahriman], "name")
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ def test_run_sort_by(args: argparse.Namespace, configuration: Configuration, aur
|
||||
mocker.patch("ahriman.core.alpm.aur.AUR.multisearch", return_value=[aur_package_ahriman])
|
||||
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
|
||||
|
||||
Search.run(args, "x86_64", configuration, True)
|
||||
Search.run(args, "x86_64", configuration, True, False)
|
||||
sort_mock.assert_called_once_with([aur_package_ahriman], "field")
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||
:param args: command line arguments fixture
|
||||
:return: generated arguments for these test cases
|
||||
"""
|
||||
args.build_as_user = "ahriman"
|
||||
args.build_command = "ahriman"
|
||||
args.from_configuration = Path("/usr/share/devtools/pacman-extra.conf")
|
||||
args.no_multilib = False
|
||||
@ -41,7 +42,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
|
||||
paths = RepositoryPaths(configuration.getpath("repository", "root"), "x86_64")
|
||||
|
||||
Setup.run(args, "x86_64", configuration, True)
|
||||
Setup.run(args, "x86_64", configuration, True, False)
|
||||
ahriman_configuration_mock.assert_called_once_with(args, "x86_64", args.repository, configuration.include)
|
||||
devtools_configuration_mock.assert_called_once_with(args.build_command, "x86_64", args.from_configuration,
|
||||
args.no_multilib, args.repository, paths)
|
||||
@ -73,6 +74,7 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
|
||||
set_option_mock.assert_has_calls([
|
||||
mock.call(Configuration.section_name("build", "x86_64"), "build_command", str(command)),
|
||||
mock.call("repository", "name", args.repository),
|
||||
mock.call(Configuration.section_name("build", "x86_64"), "makechrootpkg_flags", f"-U {args.build_as_user}"),
|
||||
mock.call(Configuration.section_name("sign", "x86_64"), "target",
|
||||
" ".join([target.name.lower() for target in args.sign_target])),
|
||||
mock.call(Configuration.section_name("sign", "x86_64"), "key", args.sign_key),
|
||||
|
@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.sign")
|
||||
|
||||
Sign.run(args, "x86_64", configuration, True)
|
||||
Sign.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with([])
|
||||
|
@ -35,7 +35,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, package_ahr
|
||||
(package_python_schedule, BuildStatus(BuildStatusEnum.Failed))])
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
Status.run(args, "x86_64", configuration, True)
|
||||
Status.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with()
|
||||
packages_mock.assert_called_once_with(None)
|
||||
print_mock.assert_has_calls([mock.call(False) for _ in range(3)])
|
||||
@ -53,7 +53,7 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, pac
|
||||
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
Status.run(args, "x86_64", configuration, True)
|
||||
Status.run(args, "x86_64", configuration, True, False)
|
||||
print_mock.assert_has_calls([mock.call(True) for _ in range(2)])
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ def test_run_with_package_filter(args: argparse.Namespace, configuration: Config
|
||||
packages_mock = mocker.patch("ahriman.core.status.client.Client.get",
|
||||
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
|
||||
|
||||
Status.run(args, "x86_64", configuration, True)
|
||||
Status.run(args, "x86_64", configuration, True, False)
|
||||
packages_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ def test_run_by_status(args: argparse.Namespace, configuration: Configuration, p
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
Status.run(args, "x86_64", configuration, True)
|
||||
Status.run(args, "x86_64", configuration, True, False)
|
||||
print_mock.assert_has_calls([mock.call(False) for _ in range(2)])
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
|
||||
|
||||
Status.run(args, "x86_64", configuration, True)
|
||||
Status.run(args, "x86_64", configuration, True, False)
|
||||
load_mock.assert_called_once_with(configuration)
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
update_self_mock = mocker.patch("ahriman.core.status.client.Client.update_self")
|
||||
|
||||
StatusUpdate.run(args, "x86_64", configuration, True)
|
||||
StatusUpdate.run(args, "x86_64", configuration, True, False)
|
||||
update_self_mock.assert_called_once_with(args.status)
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ def test_run_packages(args: argparse.Namespace, configuration: Configuration, pa
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.update")
|
||||
|
||||
StatusUpdate.run(args, "x86_64", configuration, True)
|
||||
StatusUpdate.run(args, "x86_64", configuration, True, False)
|
||||
update_mock.assert_called_once_with(package_ahriman.base, args.status)
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, pack
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
update_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||
|
||||
StatusUpdate.run(args, "x86_64", configuration, True)
|
||||
StatusUpdate.run(args, "x86_64", configuration, True, False)
|
||||
update_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
|
||||
|
||||
StatusUpdate.run(args, "x86_64", configuration, True)
|
||||
StatusUpdate.run(args, "x86_64", configuration, True, False)
|
||||
load_mock.assert_called_once_with(configuration)
|
||||
|
||||
|
||||
|
@ -24,5 +24,5 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.sync")
|
||||
|
||||
Sync.run(args, "x86_64", configuration, True)
|
||||
Sync.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with(args.target, [])
|
||||
|
@ -34,7 +34,7 @@ def test_run(args: argparse.Namespace, package_ahriman: Package,
|
||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
|
||||
|
||||
Update.run(args, "x86_64", configuration, True)
|
||||
Update.run(args, "x86_64", configuration, True, False)
|
||||
application_mock.assert_called_once_with([package_ahriman])
|
||||
updates_mock.assert_called_once_with(args.package, args.no_aur, args.no_local, args.no_manual, args.no_vcs,
|
||||
pytest.helpers.anyvar(int))
|
||||
@ -49,7 +49,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, moc
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
updates_mock = mocker.patch("ahriman.application.application.Application.updates")
|
||||
|
||||
Update.run(args, "x86_64", configuration, True)
|
||||
Update.run(args, "x86_64", configuration, True, False)
|
||||
updates_mock.assert_called_once_with(args.package, args.no_aur, args.no_local, args.no_manual, args.no_vcs,
|
||||
pytest.helpers.anyvar(int))
|
||||
|
||||
|
@ -41,7 +41,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
get_salt_mock = mocker.patch("ahriman.application.handlers.User.get_salt")
|
||||
reload_mock = mocker.patch("ahriman.core.status.client.Client.reload_auth")
|
||||
|
||||
User.run(args, "x86_64", configuration, True)
|
||||
User.run(args, "x86_64", configuration, True, False)
|
||||
get_auth_configuration_mock.assert_called_once_with(configuration.include)
|
||||
create_configuration_mock.assert_called_once_with(
|
||||
pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), args.as_service)
|
||||
@ -63,7 +63,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, mock
|
||||
write_configuration_mock = mocker.patch("ahriman.application.handlers.User.configuration_write")
|
||||
reload_mock = mocker.patch("ahriman.core.status.client.Client.reload_auth")
|
||||
|
||||
User.run(args, "x86_64", configuration, True)
|
||||
User.run(args, "x86_64", configuration, True, False)
|
||||
get_auth_configuration_mock.assert_called_once_with(configuration.include)
|
||||
create_configuration_mock.assert_not_called()
|
||||
write_configuration_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.secure)
|
||||
@ -81,7 +81,7 @@ def test_run_no_reload(args: argparse.Namespace, configuration: Configuration, m
|
||||
mocker.patch("ahriman.application.handlers.User.configuration_write")
|
||||
reload_mock = mocker.patch("ahriman.core.status.client.Client.reload_auth")
|
||||
|
||||
User.run(args, "x86_64", configuration, True)
|
||||
User.run(args, "x86_64", configuration, True, False)
|
||||
reload_mock.assert_not_called()
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
||||
setup_mock = mocker.patch("ahriman.web.web.setup_service")
|
||||
run_mock = mocker.patch("ahriman.web.web.run_server")
|
||||
|
||||
Web.run(args, "x86_64", configuration, True)
|
||||
Web.run(args, "x86_64", configuration, True, False)
|
||||
setup_mock.assert_called_once_with("x86_64", configuration, pytest.helpers.anyvar(int))
|
||||
run_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||
|
||||
|
33
tests/ahriman/application/handlers/test_unsafe_commands.py
Normal file
33
tests/ahriman/application/handlers/test_unsafe_commands.py
Normal file
@ -0,0 +1,33 @@
|
||||
import argparse
|
||||
import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.application.ahriman import _parser
|
||||
from ahriman.application.handlers import UnsafeCommands
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must run command
|
||||
"""
|
||||
args.parser = _parser
|
||||
commands_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.get_unsafe_commands",
|
||||
return_value=["command"])
|
||||
print_mock = mocker.patch("ahriman.application.formatters.printer.Printer.print")
|
||||
|
||||
UnsafeCommands.run(args, "x86_64", configuration, True, False)
|
||||
commands_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||
print_mock.assert_called_once_with(verbose=True)
|
||||
|
||||
|
||||
def test_get_unsafe_commands() -> None:
|
||||
"""
|
||||
must return unsafe commands
|
||||
"""
|
||||
parser = _parser()
|
||||
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))
|
||||
commands = UnsafeCommands.get_unsafe_commands(parser)
|
||||
for command in commands:
|
||||
assert subparser.choices[command].get_default("unsafe")
|
@ -65,6 +65,27 @@ def test_subparsers_aur_search_architecture(parser: argparse.ArgumentParser) ->
|
||||
assert args.architecture == [""]
|
||||
|
||||
|
||||
def test_subparsers_help_commands_unsafe(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
help-commands-unsafe command must imply architecture list, lock, no-report, quiet, unsafe and parser
|
||||
"""
|
||||
args = parser.parse_args(["help-commands-unsafe"])
|
||||
assert args.architecture == [""]
|
||||
assert args.lock is None
|
||||
assert args.no_report
|
||||
assert args.quiet
|
||||
assert args.unsafe
|
||||
assert args.parser is not None and args.parser()
|
||||
|
||||
|
||||
def test_subparsers_help_commands_unsafe_architecture(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
help-ommands-unsafe command must correctly parse architecture list
|
||||
"""
|
||||
args = parser.parse_args(["-a", "x86_64", "help-commands-unsafe"])
|
||||
assert args.architecture == [""]
|
||||
|
||||
|
||||
def test_subparsers_key_import(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
key-import command must imply architecture list, lock and no-report
|
||||
|
@ -82,7 +82,7 @@ def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
check_user_patch = mocker.patch("ahriman.application.lock.check_user")
|
||||
lock.check_user()
|
||||
check_user_patch.assert_called_once_with(lock.root)
|
||||
check_user_patch.assert_called_once_with(lock.root, False)
|
||||
|
||||
|
||||
def test_check_user_exception(lock: Lock, mocker: MockerFixture) -> None:
|
||||
|
@ -19,7 +19,7 @@ def cleaner(configuration: Configuration, mocker: MockerFixture) -> Cleaner:
|
||||
:return: cleaner test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Cleaner("x86_64", configuration, no_report=True)
|
||||
return Cleaner("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -36,7 +36,7 @@ def executor(configuration: Configuration, mocker: MockerFixture) -> Executor:
|
||||
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_manual")
|
||||
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Executor("x86_64", configuration, no_report=True)
|
||||
return Executor("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -48,7 +48,7 @@ def repository(configuration: Configuration, mocker: MockerFixture) -> Repositor
|
||||
:return: repository test instance
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return Repository("x86_64", configuration, no_report=True)
|
||||
return Repository("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -58,7 +58,7 @@ def properties(configuration: Configuration) -> Properties:
|
||||
:param configuration: configuration fixture
|
||||
:return: properties test instance
|
||||
"""
|
||||
return Properties("x86_64", configuration, no_report=True)
|
||||
return Properties("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -75,4 +75,4 @@ def update_handler(configuration: Configuration, mocker: MockerFixture) -> Updat
|
||||
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_manual")
|
||||
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
return UpdateHandler("x86_64", configuration, no_report=True)
|
||||
return UpdateHandler("x86_64", configuration, no_report=True, unsafe=False)
|
||||
|
@ -12,7 +12,7 @@ def test_create_tree_on_load(configuration: Configuration, mocker: MockerFixture
|
||||
"""
|
||||
mocker.patch("ahriman.core.repository.properties.check_user")
|
||||
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
Properties("x86_64", configuration, True)
|
||||
Properties("x86_64", configuration, True, False)
|
||||
|
||||
tree_create_mock.assert_called_once_with()
|
||||
|
||||
@ -23,7 +23,7 @@ def test_create_tree_on_load_unsafe(configuration: Configuration, mocker: Mocker
|
||||
"""
|
||||
mocker.patch("ahriman.core.repository.properties.check_user", side_effect=UnsafeRun(0, 1))
|
||||
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
Properties("x86_64", configuration, True)
|
||||
Properties("x86_64", configuration, True, False)
|
||||
|
||||
tree_create_mock.assert_not_called()
|
||||
|
||||
@ -34,7 +34,7 @@ def test_create_dummy_report_client(configuration: Configuration, mocker: Mocker
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
|
||||
properties = Properties("x86_64", configuration, True)
|
||||
properties = Properties("x86_64", configuration, True, False)
|
||||
|
||||
load_mock.assert_not_called()
|
||||
assert not isinstance(properties.reporter, WebClient)
|
||||
@ -46,6 +46,6 @@ def test_create_full_report_client(configuration: Configuration, mocker: MockerF
|
||||
"""
|
||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||
load_mock = mocker.patch("ahriman.core.status.client.Client.load")
|
||||
Properties("x86_64", configuration, False)
|
||||
Properties("x86_64", configuration, False, False)
|
||||
|
||||
load_mock.assert_called_once_with(configuration)
|
||||
|
@ -58,7 +58,7 @@ def test_check_user(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
cwd = Path.cwd()
|
||||
mocker.patch("os.getuid", return_value=cwd.stat().st_uid)
|
||||
check_user(cwd)
|
||||
check_user(cwd, False)
|
||||
|
||||
|
||||
def test_check_user_no_directory(mocker: MockerFixture) -> None:
|
||||
@ -66,7 +66,7 @@ def test_check_user_no_directory(mocker: MockerFixture) -> None:
|
||||
must not fail in case if no directory found
|
||||
"""
|
||||
mocker.patch("pathlib.Path.exists", return_value=False)
|
||||
check_user(Path.cwd())
|
||||
check_user(Path.cwd(), False)
|
||||
|
||||
|
||||
def test_check_user_exception(mocker: MockerFixture) -> None:
|
||||
@ -77,7 +77,16 @@ def test_check_user_exception(mocker: MockerFixture) -> None:
|
||||
mocker.patch("os.getuid", return_value=cwd.stat().st_uid + 1)
|
||||
|
||||
with pytest.raises(UnsafeRun):
|
||||
check_user(cwd)
|
||||
check_user(cwd, False)
|
||||
|
||||
|
||||
def test_check_unsafe(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip check if unsafe flag is set
|
||||
"""
|
||||
cwd = Path.cwd()
|
||||
mocker.patch("os.getuid", return_value=cwd.stat().st_uid + 1)
|
||||
check_user(cwd, True)
|
||||
|
||||
|
||||
def test_filter_json(package_ahriman: Package) -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user