mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-09-11 11:20:02 +00:00
feat: add reload command and api endpoints
This commit is contained in:
70
src/ahriman/application/handlers/reload.py
Normal file
70
src/ahriman/application/handlers/reload.py
Normal file
@ -0,0 +1,70 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 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 ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Reload(Handler):
|
||||
"""
|
||||
web server reload handler
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(repository_id, configuration, report=True)
|
||||
client = application.repository.reporter
|
||||
client.configuration_reload()
|
||||
|
||||
@staticmethod
|
||||
def _set_web_reload_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for web reload subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("web-reload", help="reload configuration",
|
||||
description="reload web server configuration",
|
||||
epilog="This method forces the web server to reload its configuration. "
|
||||
"Note, however, that this method does not apply all configuration changes "
|
||||
"(like ports, authentication, etc)")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_web_reload_parser]
|
@ -81,6 +81,11 @@ class Client:
|
||||
|
||||
return make_local_client()
|
||||
|
||||
def configuration_reload(self) -> None:
|
||||
"""
|
||||
reload configuration
|
||||
"""
|
||||
|
||||
def event_add(self, event: Event) -> None:
|
||||
"""
|
||||
create new event
|
||||
|
@ -17,6 +17,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# pylint: disable=too-many-public-methods
|
||||
import contextlib
|
||||
|
||||
from urllib.parse import quote_plus as url_encode
|
||||
@ -165,6 +166,13 @@ class WebClient(Client, SyncAhrimanClient):
|
||||
"""
|
||||
return f"{self.address}/api/v1/status"
|
||||
|
||||
def configuration_reload(self) -> None:
|
||||
"""
|
||||
reload configuration
|
||||
"""
|
||||
with contextlib.suppress(Exception):
|
||||
self.make_request("POST", f"{self.address}/api/v1/service/config")
|
||||
|
||||
def event_add(self, event: Event) -> None:
|
||||
"""
|
||||
create new event
|
||||
|
@ -22,6 +22,7 @@ from ahriman.web.schemas.aur_package_schema import AURPackageSchema
|
||||
from ahriman.web.schemas.auth_schema import AuthSchema
|
||||
from ahriman.web.schemas.build_options_schema import BuildOptionsSchema
|
||||
from ahriman.web.schemas.changes_schema import ChangesSchema
|
||||
from ahriman.web.schemas.configuration_schema import ConfigurationSchema
|
||||
from ahriman.web.schemas.counters_schema import CountersSchema
|
||||
from ahriman.web.schemas.dependencies_schema import DependenciesSchema
|
||||
from ahriman.web.schemas.error_schema import ErrorSchema
|
||||
|
39
src/ahriman/web/schemas/configuration_schema.py
Normal file
39
src/ahriman/web/schemas/configuration_schema.py
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 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/>.
|
||||
#
|
||||
from ahriman.web.apispec import Schema, fields
|
||||
|
||||
|
||||
class ConfigurationSchema(Schema):
|
||||
"""
|
||||
response configuration schema
|
||||
"""
|
||||
|
||||
key = fields.String(required=True, metadata={
|
||||
"description": "Configuration key",
|
||||
"example": "host",
|
||||
})
|
||||
section = fields.String(required=True, metadata={
|
||||
"description": "Configuration section",
|
||||
"example": "web",
|
||||
})
|
||||
value = fields.String(required=True, metadata={
|
||||
"description": "Configuration value",
|
||||
"example": "127.0.0.1",
|
||||
})
|
84
src/ahriman/web/views/v1/service/config.py
Normal file
84
src/ahriman/web/views/v1/service/config.py
Normal file
@ -0,0 +1,84 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 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/>.
|
||||
#
|
||||
from aiohttp.web import HTTPNoContent, Response, json_response
|
||||
from typing import ClassVar
|
||||
|
||||
from ahriman.core.formatters import ConfigurationPrinter
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.apispec.decorators import apidocs
|
||||
from ahriman.web.schemas import ConfigurationSchema
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
class ConfigView(BaseView):
|
||||
"""
|
||||
configuration control view
|
||||
|
||||
Attributes:
|
||||
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||
POST_PERMISSION(UserAccess): (class attribute) post permissions of self
|
||||
"""
|
||||
|
||||
GET_PERMISSION = POST_PERMISSION = UserAccess.Full # type: ClassVar[UserAccess]
|
||||
ROUTES = ["/api/v1/service/config"]
|
||||
|
||||
@apidocs(
|
||||
tags=["Actions"],
|
||||
summary="Get configuration",
|
||||
description="Get current web service configuration as nested dictionary",
|
||||
permission=GET_PERMISSION,
|
||||
schema=ConfigurationSchema(many=True),
|
||||
)
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current web service configuration
|
||||
|
||||
Returns:
|
||||
Response: current web service configuration as nested dictionary
|
||||
"""
|
||||
dump = self.configuration.dump()
|
||||
|
||||
response = [
|
||||
{
|
||||
"section": section,
|
||||
"key": key,
|
||||
"value": value,
|
||||
} for section, values in dump.items()
|
||||
for key, value in values.items()
|
||||
if key not in ConfigurationPrinter.HIDE_KEYS
|
||||
]
|
||||
return json_response(response)
|
||||
|
||||
@apidocs(
|
||||
tags=["Actions"],
|
||||
summary="Reload configuration",
|
||||
description="Reload configuration from current files",
|
||||
permission=POST_PERMISSION,
|
||||
)
|
||||
async def post(self) -> None:
|
||||
"""
|
||||
reload web service configuration
|
||||
|
||||
Raises:
|
||||
HTTPNoContent: on success response
|
||||
"""
|
||||
self.configuration.reload()
|
||||
|
||||
raise HTTPNoContent
|
Reference in New Issue
Block a user