add curl examples to web views

This commit is contained in:
Evgenii Alekseev 2022-11-23 22:24:36 +02:00
parent 9e0dd3ae97
commit a7c9183aa0
13 changed files with 296 additions and 23 deletions

View File

@ -1,6 +1,7 @@
version: 2 version: 2
formats: all formats:
- pdf
build: build:
os: ubuntu-20.04 os: ubuntu-20.04
@ -10,6 +11,7 @@ build:
sphinx: sphinx:
builder: html builder: html
configuration: docs/conf.py configuration: docs/conf.py
fail_on_warning: true
python: python:
install: install:

View File

@ -27,6 +27,8 @@ on_rtd = os.environ.get("READTHEDOCS", None) == "True"
for module in ( for module in (
"pyalpm", "pyalpm",
): ):
if module in sys.modules:
continue
sys.modules[module] = mock.Mock() sys.modules[module] = mock.Mock()
@ -77,7 +79,7 @@ html_theme = "default" if on_rtd else "alabaster"
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"] html_static_path = []
add_module_names = False add_module_names = False

View File

@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from aiohttp.web import HTTPAccepted from aiohttp.web import HTTPNoContent
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -40,16 +40,31 @@ class AddView(BaseView):
JSON body must be supplied, the following model is used:: JSON body must be supplied, the following model is used::
{ {
"packages": "ahriman" # either list of packages or package name as in AUR "packages": ["ahriman"] # either list of packages or package name as in AUR
} }
Raises: Raises:
HTTPAccepted: in case of success response HTTPNoContent: in case of success response
HTTPBadRequest: if bad data is supplied
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/service/add' -d '{"packages": ["ahriman"]}'
> POST /api/v1/service/add HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 25
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 18:44:21 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
data = await self.extract_data(["packages"]) data = await self.extract_data(["packages"])
packages = data.get("packages", []) packages = data.get("packages", [])
self.spawner.packages_add(packages, now=True) self.spawner.packages_add(packages, now=True)
raise HTTPAccepted() raise HTTPNoContent()

View File

@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from aiohttp.web import HTTPAccepted, HTTPBadRequest from aiohttp.web import HTTPBadRequest, HTTPNoContent
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -40,12 +40,28 @@ class RemoveView(BaseView):
JSON body must be supplied, the following model is used:: JSON body must be supplied, the following model is used::
{ {
"packages": "ahriman", # either list of packages or package name "packages": ["ahriman"] # either list of packages or package name
} }
Raises: Raises:
HTTPAccepted: in case of success response
HTTPBadRequest: if bad data is supplied HTTPBadRequest: if bad data is supplied
HTTPNoContent: in case of success response
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/service/remove' -d '{"packages": ["ahriman"]}'
> POST /api/v1/service/remove HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 25
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 18:57:56 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
try: try:
data = await self.extract_data(["packages"]) data = await self.extract_data(["packages"])
@ -55,4 +71,4 @@ class RemoveView(BaseView):
self.spawner.packages_remove(packages) self.spawner.packages_remove(packages)
raise HTTPAccepted() raise HTTPNoContent()

View File

@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from aiohttp.web import HTTPAccepted, HTTPBadRequest from aiohttp.web import HTTPBadRequest, HTTPNoContent
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -40,12 +40,28 @@ class RequestView(BaseView):
JSON body must be supplied, the following model is used:: JSON body must be supplied, the following model is used::
{ {
"packages": "ahriman" # either list of packages or package name as in AUR "packages": ["ahriman"] # either list of packages or package name as in AUR
} }
Raises: Raises:
HTTPAccepted: in case of success response
HTTPBadRequest: if bad data is supplied HTTPBadRequest: if bad data is supplied
HTTPNoContent: in case of success response
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/service/request' -d '{"packages": ["ahriman"]}'
> POST /api/v1/service/request HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 25
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 18:59:32 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
try: try:
data = await self.extract_data(["packages"]) data = await self.extract_data(["packages"])
@ -55,4 +71,4 @@ class RequestView(BaseView):
self.spawner.packages_add(packages, now=False) self.spawner.packages_add(packages, now=False)
raise HTTPAccepted() raise HTTPNoContent()

View File

@ -39,15 +39,30 @@ class SearchView(BaseView):
async def get(self) -> Response: async def get(self) -> Response:
""" """
search packages in AUR search packages in AUR. Search string (non-empty) must be supplied as ``for`` parameter
search string (non empty) must be supplied as ``for`` parameter
Returns: Returns:
Response: 200 with found package bases and descriptions sorted by base Response: 200 with found package bases and descriptions sorted by base
Raises: Raises:
HTTPNotFound: if no packages found HTTPNotFound: if no packages found
Examples:
Example of command by using curl::
$ curl -v -H 'Accept: application/json' 'http://example.com/api/v1/service/search?for=ahriman'
> GET /api/v1/service/search?for=ahriman HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 148
< Date: Wed, 23 Nov 2022 19:07:13 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
[{"package": "ahriman", "description": "ArcH linux ReposItory MANager"}, {"package": "ahriman-git", "description": "ArcH Linux ReposItory MANager"}]
""" """
search: List[str] = self.request.query.getall("for", default=[]) search: List[str] = self.request.query.getall("for", default=[])
packages = AUR.multisearch(*search, pacman=self.service.repository.pacman) packages = AUR.multisearch(*search, pacman=self.service.repository.pacman)

View File

@ -46,6 +46,20 @@ class LogsView(BaseView):
Raises: Raises:
HTTPNoContent: on success response HTTPNoContent: on success response
Examples:
Example of command by using curl::
$ curl -v -XDELETE 'http://example.com/api/v1/packages/ahriman/logs'
> DELETE /api/v1/packages/ahriman/logs HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:26:40 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
self.service.remove_logs(package_base, None) self.service.remove_logs(package_base, None)
@ -58,6 +72,23 @@ class LogsView(BaseView):
Returns: Returns:
Response: 200 with package logs on success Response: 200 with package logs on success
Examples:
Example of command by using curl::
$ curl -v -H 'Accept: application/json' 'http://example.com/api/v1/packages/ahriman/logs'
> GET /api/v1/packages/ahriman/logs HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 100112
< Date: Wed, 23 Nov 2022 19:24:14 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
{"package_base": "ahriman", "status": {"status": "success", "timestamp": 1669231136}, "logs": "[2022-11-23 19:17:32] clone remote https://aur.archlinux.org/ahriman.git to /tmp/tmpy9j6fq9p using branch master"}
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
@ -89,6 +120,22 @@ class LogsView(BaseView):
Raises: Raises:
HTTPBadRequest: if bad data is supplied HTTPBadRequest: if bad data is supplied
HTTPNoContent: in case of success response HTTPNoContent: in case of success response
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/packages/ahriman/logs' -d '{"created": 1669231764.042444, "message": "my log message", "process_id": 1}'
> POST /api/v1/packages/ahriman/logs HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 76
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:30:45 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
data = await self.extract_data() data = await self.extract_data()

View File

@ -46,6 +46,20 @@ class PackageView(BaseView):
Raises: Raises:
HTTPNoContent: on success response HTTPNoContent: on success response
Examples:
Example of command by using curl::
$ curl -v -XDELETE 'http://example.com/api/v1/packages/ahriman'
> DELETE /api/v1/packages/ahriman HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:43:40 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
self.service.remove(package_base) self.service.remove(package_base)
@ -61,6 +75,23 @@ class PackageView(BaseView):
Raises: Raises:
HTTPNotFound: if no package was found HTTPNotFound: if no package was found
Examples:
Example of command by using curl::
$ curl -v -H 'Accept: application/json' 'http://example.com/api/v1/packages/ahriman'
> GET /api/v1/packages/ahriman HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 743
< Date: Wed, 23 Nov 2022 19:41:01 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
[{"package": {"base": "ahriman", "version": "2.3.0-1", "remote": {"git_url": "https://aur.archlinux.org/ahriman.git", "web_url": "https://aur.archlinux.org/packages/ahriman", "path": ".", "branch": "master", "source": "aur"}, "packages": {"ahriman": {"architecture": "any", "archive_size": 247573, "build_date": 1669231069, "depends": ["devtools", "git", "pyalpm", "python-inflection", "python-passlib", "python-requests", "python-setuptools", "python-srcinfo"], "description": "ArcH linux ReposItory MANager", "filename": "ahriman-2.3.0-1-any.pkg.tar.zst", "groups": [], "installed_size": 1676153, "licenses": ["GPL3"], "provides": [], "url": "https://github.com/arcan1s/ahriman"}}}, "status": {"status": "success", "timestamp": 1669231136}}]
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
@ -85,13 +116,29 @@ class PackageView(BaseView):
{ {
"status": "unknown", # package build status string, must be valid ``BuildStatusEnum`` "status": "unknown", # package build status string, must be valid ``BuildStatusEnum``
"package": {} # package body (use ``dataclasses.asdict`` to generate one), optional. "package": {} # package body (use ``dataclasses.asdict`` to generate one), optional.
# Must be supplied in case if package base is unknown # Must be supplied in case if package base is unknown
} }
Raises: Raises:
HTTPBadRequest: if bad data is supplied HTTPBadRequest: if bad data is supplied
HTTPNoContent: in case of success response HTTPNoContent: in case of success response
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/packages/ahriman' -d '{"status": "success"}'
> POST /api/v1/packages/ahriman HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 21
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:42:49 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
data = await self.extract_data() data = await self.extract_data()

View File

@ -42,6 +42,23 @@ class PackagesView(BaseView):
Returns: Returns:
Response: 200 with package description on success Response: 200 with package description on success
Examples:
Example of command by using curl::
$ curl -v -H 'Accept: application/json' 'http://example.com/api/v1/packages'
> GET /api/v1/packages HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 2687
< Date: Wed, 23 Nov 2022 19:35:24 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
[{"package": {"base": "ahriman", "version": "2.3.0-1", "remote": {"git_url": "https://aur.archlinux.org/ahriman.git", "web_url": "https://aur.archlinux.org/packages/ahriman", "path": ".", "branch": "master", "source": "aur"}, "packages": {"ahriman": {"architecture": "any", "archive_size": 247573, "build_date": 1669231069, "depends": ["devtools", "git", "pyalpm", "python-inflection", "python-passlib", "python-requests", "python-setuptools", "python-srcinfo"], "description": "ArcH linux ReposItory MANager", "filename": "ahriman-2.3.0-1-any.pkg.tar.zst", "groups": [], "installed_size": 1676153, "licenses": ["GPL3"], "provides": [], "url": "https://github.com/arcan1s/ahriman"}}}, "status": {"status": "success", "timestamp": 1669231136}}]
""" """
response = [ response = [
{ {
@ -57,6 +74,20 @@ class PackagesView(BaseView):
Raises: Raises:
HTTPNoContent: on success response HTTPNoContent: on success response
Examples:
Example of command by using curl::
$ curl -v -XPOST 'http://example.com/api/v1/packages'
> POST /api/v1/packages HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:38:06 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
self.service.load() self.service.load()

View File

@ -46,6 +46,23 @@ class StatusView(BaseView):
Returns: Returns:
Response: 200 with service status object Response: 200 with service status object
Examples:
Example of command by using curl::
$ curl -v -H 'Accept: application/json' 'http://example.com/api/v1/status'
> GET /api/v1/status HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 222
< Date: Wed, 23 Nov 2022 19:32:31 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
{"status": {"status": "success", "timestamp": 1669231237}, "architecture": "x86_64", "packages": {"total": 4, "unknown": 0, "pending": 0, "building": 0, "failed": 0, "success": 4}, "repository": "repo", "version": "2.3.0"}
""" """
counters = Counters.from_packages(self.service.packages) counters = Counters.from_packages(self.service.packages)
status = InternalStatus( status = InternalStatus(
@ -70,6 +87,22 @@ class StatusView(BaseView):
Raises: Raises:
HTTPBadRequest: if bad data is supplied HTTPBadRequest: if bad data is supplied
HTTPNoContent: in case of success response HTTPNoContent: in case of success response
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/status' -d '{"status": "success"}'
> POST /api/v1/status HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 21
>
< HTTP/1.1 204 No Content
< Date: Wed, 23 Nov 2022 19:33:57 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
""" """
try: try:
data = await self.extract_data() data = await self.extract_data()

View File

@ -41,12 +41,17 @@ class LoginView(BaseView):
OAuth2 response handler OAuth2 response handler
In case if code provided it will do a request to get user email. In case if no code provided it will redirect In case if code provided it will do a request to get user email. In case if no code provided it will redirect
to authorization url provided by OAuth client to authorization url provided by OAuth client.
The authentication session will be passed in ``Set-Cookie`` header.
Raises: Raises:
HTTPFound: on success response HTTPFound: on success response
HTTPMethodNotAllowed: in case if method is used, but OAuth is disabled HTTPMethodNotAllowed: in case if method is used, but OAuth is disabled
HTTPUnauthorized: if case of authorization error HTTPUnauthorized: if case of authorization error
Examples:
This request must not be used directly.
""" """
from ahriman.core.auth import OAuth from ahriman.core.auth import OAuth
@ -78,9 +83,32 @@ class LoginView(BaseView):
"password": "pa55w0rd" # password to use for login "password": "pa55w0rd" # password to use for login
} }
The authentication session will be passed in ``Set-Cookie`` header.
Raises: Raises:
HTTPFound: on success response HTTPFound: on success response
HTTPUnauthorized: if case of authorization error HTTPUnauthorized: if case of authorization error
Examples:
Example of command by using curl::
$ curl -v -H 'Content-Type: application/json' 'http://example.com/api/v1/login' -d '{"username": "test", "password": "test"}'
> POST /api/v1/login HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 40
>
< HTTP/1.1 302 Found
< Content-Type: text/plain; charset=utf-8
< Location: /
< Content-Length: 10
< Set-Cookie: ...
< Date: Wed, 23 Nov 2022 17:51:27 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
302: Found
""" """
data = await self.extract_data() data = await self.extract_data()
username = data.get("username") username = data.get("username")

View File

@ -37,10 +37,31 @@ class LogoutView(BaseView):
async def post(self) -> None: async def post(self) -> None:
""" """
logout user from the service. No parameters supported here logout user from the service. No parameters supported here.
The server will respond with ``Set-Cookie`` header, in which API session cookie will be nullified.
Raises: Raises:
HTTPFound: on success response HTTPFound: on success response
Examples:
Example of command by using curl::
$ curl -v -XPOST 'http://example.com/api/v1/logout'
> POST /api/v1/logout HTTP/1.1
> Host: example.com
> User-Agent: curl/7.86.0
> Accept: */*
>
< HTTP/1.1 302 Found
< Content-Type: text/plain; charset=utf-8
< Location: /
< Content-Length: 10
< Set-Cookie: ...
< Date: Wed, 23 Nov 2022 19:10:51 GMT
< Server: Python/3.10 aiohttp/3.8.3
<
302: Found
""" """
try: try:
await check_authorized(self.request) await check_authorized(self.request)

View File

@ -44,7 +44,7 @@ deps =
{[tox]dependencies} {[tox]dependencies}
-e .[docs] -e .[docs]
commands = commands =
sphinx-build -b html -a -j auto docs docs/html sphinx-build -b html -a -j auto -W docs docs/html
[testenv:tests] [testenv:tests]
deps = deps =