diff --git a/src/ahriman/core/watcher/watcher.py b/src/ahriman/core/watcher/watcher.py
index e2686a6a..dad851a7 100644
--- a/src/ahriman/core/watcher/watcher.py
+++ b/src/ahriman/core/watcher/watcher.py
@@ -52,6 +52,13 @@ class Watcher:
'''
return [pair for pair in self.known.values()]
+ def get(self, base: str) -> Tuple[Package, BuildStatus]:
+ '''
+ get current package base build status
+ :return: package and its status
+ '''
+ return self.known[base]
+
def load(self) -> None:
'''
load packages from local repository. In case if last status is known, it will use it
diff --git a/src/ahriman/core/watcher/web_client.py b/src/ahriman/core/watcher/web_client.py
index 02b0d284..c0854991 100644
--- a/src/ahriman/core/watcher/web_client.py
+++ b/src/ahriman/core/watcher/web_client.py
@@ -21,7 +21,6 @@ import logging
import requests
from dataclasses import asdict
-from typing import Any, Dict
from ahriman.core.watcher.client import Client
from ahriman.models.build_status import BuildStatusEnum
@@ -67,7 +66,7 @@ class WebClient(Client):
:param package: package properties
:param status: current package build status
'''
- payload: Dict[str, Any] = {
+ payload = {
'status': status.value,
'package': asdict(package)
}
@@ -95,7 +94,7 @@ class WebClient(Client):
:param base: package base to update
:param status: current package build status
'''
- payload: Dict[str, Any] = {'status': status.value}
+ payload = {'status': status.value}
try:
response = requests.post(self._package_url(base), json=payload)
@@ -108,7 +107,7 @@ class WebClient(Client):
update ahriman status itself
:param status: current ahriman status
'''
- payload: Dict[str, Any] = {'status': status.value}
+ payload = {'status': status.value}
try:
response = requests.post(self._ahriman_url(), json=payload)
diff --git a/src/ahriman/web/routes.py b/src/ahriman/web/routes.py
index 6438a50d..f7f63e10 100644
--- a/src/ahriman/web/routes.py
+++ b/src/ahriman/web/routes.py
@@ -34,21 +34,27 @@ def setup_routes(application: Application) -> None:
GET / get build status page
GET /index.html same as above
+ GET /api/v1/ahriman get current service status
POST /api/v1/ahriman update service status
+ GET /api/v1/packages get all known packages
POST /api/v1/packages force update every package from repository
- POST /api/v1/package/:base update package base status
DELETE /api/v1/package/:base delete package base from status page
+ GET /api/v1/package/:base get package base status
+ POST /api/v1/package/:base update package base status
:param application: web application instance
'''
application.router.add_get('/', IndexView)
application.router.add_get('/index.html', IndexView)
+ application.router.add_get('/api/v1/ahriman', AhrimanView)
application.router.add_post('/api/v1/ahriman', AhrimanView)
+ application.router.add_get('/api/v1/packages', PackagesView)
application.router.add_post('/api/v1/packages', PackagesView)
application.router.add_delete('/api/v1/packages/{package}', PackageView)
+ application.router.add_get('/api/v1/packages/{package}', PackageView)
application.router.add_post('/api/v1/packages/{package}', PackageView)
diff --git a/src/ahriman/web/views/ahriman.py b/src/ahriman/web/views/ahriman.py
index e61bf146..2f190624 100644
--- a/src/ahriman/web/views/ahriman.py
+++ b/src/ahriman/web/views/ahriman.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from aiohttp.web import HTTPBadRequest, HTTPOk, Response
+from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
from ahriman.models.build_status import BuildStatusEnum
from ahriman.web.views.base import BaseView
@@ -28,6 +28,13 @@ class AhrimanView(BaseView):
service status web view
'''
+ async def get(self) -> Response:
+ '''
+ get current service status
+ :return: 200 with service status object
+ '''
+ return json_response(AhrimanView.status_view(self.service.status))
+
async def post(self) -> Response:
'''
update service status
@@ -37,7 +44,7 @@ class AhrimanView(BaseView):
"status": "unknown", # service status string, must be valid `BuildStatusEnum`
}
- :return: 200 on success
+ :return: 204 on success
'''
data = await self.request.json()
@@ -48,4 +55,4 @@ class AhrimanView(BaseView):
self.service.update_self(status)
- return HTTPOk()
+ return HTTPNoContent()
diff --git a/src/ahriman/web/views/base.py b/src/ahriman/web/views/base.py
index e5f31ab3..3820b1c2 100644
--- a/src/ahriman/web/views/base.py
+++ b/src/ahriman/web/views/base.py
@@ -17,9 +17,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
+from dataclasses import asdict
+from typing import Any, Dict
+
from aiohttp.web import View
from ahriman.core.watcher.watcher import Watcher
+from ahriman.models.build_status import BuildStatus
+from ahriman.models.package import Package
class BaseView(View):
@@ -34,3 +39,28 @@ class BaseView(View):
'''
watcher: Watcher = self.request.app['watcher']
return watcher
+
+ @staticmethod
+ def package_view(package: Package, status: BuildStatus) -> Dict[str, Any]:
+ '''
+ generate json package view
+ :param package: package definitions
+ :param status: package build status
+ :return: json-friendly dictionary
+ '''
+ return {
+ 'status': BaseView.status_view(status),
+ 'package': asdict(package)
+ }
+
+ @staticmethod
+ def status_view(status: BuildStatus) -> Dict[str, Any]:
+ '''
+ generate json status view
+ :param status: build status
+ :return: json-friendly dictionary
+ '''
+ return {
+ 'status': status.status.value,
+ 'timestamp': status.timestamp
+ }
diff --git a/src/ahriman/web/views/package.py b/src/ahriman/web/views/package.py
index 061aa1ac..179b795e 100644
--- a/src/ahriman/web/views/package.py
+++ b/src/ahriman/web/views/package.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from aiohttp.web import HTTPBadRequest, HTTPOk, Response
+from aiohttp.web import HTTPBadRequest, HTTPNoContent, HTTPNotFound, Response, json_response
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package
@@ -29,15 +29,30 @@ class PackageView(BaseView):
package base specific web view
'''
+ async def get(self) -> Response:
+ '''
+ get current package base status
+ :return: 200 with package description on success
+ '''
+ base = self.request.match_info['package']
+
+ try:
+ package, status = self.service.get(base)
+ except KeyError:
+ raise HTTPNotFound()
+
+ response = PackageView.package_view(package, status)
+ return json_response(response)
+
async def delete(self) -> Response:
'''
delete package base from status page
- :return: 200 on success
+ :return: 204 on success
'''
base = self.request.match_info['package']
self.service.remove(base)
- return HTTPOk()
+ return HTTPNoContent()
async def post(self) -> Response:
'''
@@ -50,7 +65,7 @@ class PackageView(BaseView):
# Must be supplied in case if package base is unknown
}
- :return: 200 on success
+ :return: 204 on success
'''
base = self.request.match_info['package']
data = await self.request.json()
@@ -66,4 +81,4 @@ class PackageView(BaseView):
except KeyError:
raise HTTPBadRequest(text=f'Package {base} is unknown, but no package body set')
- return HTTPOk()
+ return HTTPNoContent()
diff --git a/src/ahriman/web/views/packages.py b/src/ahriman/web/views/packages.py
index 911516f0..53d8d44f 100644
--- a/src/ahriman/web/views/packages.py
+++ b/src/ahriman/web/views/packages.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from aiohttp.web import HTTPOk, Response
+from aiohttp.web import HTTPNoContent, Response, json_response
from ahriman.web.views.base import BaseView
@@ -27,11 +27,22 @@ class PackagesView(BaseView):
global watcher view
'''
+ async def get(self) -> Response:
+ '''
+ get current packages status
+ :return: 200 with package description on success
+ '''
+ response = [
+ PackagesView.package_view(package, status)
+ for package, status in self.service.packages
+ ]
+ return json_response(response)
+
async def post(self) -> Response:
'''
reload all packages from repository. No parameters supported here
- :return: 200 on success
+ :return: 204 on success
'''
self.service.load()
- return HTTPOk()
+ return HTTPNoContent()