-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Announcements entrypoint at the web-api (⚠️ devops) (#4487)
Co-authored-by: Odei Maiz <[email protected]>
- Loading branch information
Showing
26 changed files
with
673 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
# | ||
|
||
|
||
WEBSERVER_ANNOUNCEMENTS=0 | ||
WEBSERVER_ACTIVITY=null | ||
WEBSERVER_CATALOG=null | ||
WEBSERVER_NOTIFICATIONS=0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
paths: | ||
/announcements: | ||
get: | ||
tags: | ||
- announcements | ||
summary: List Announcements | ||
operationId: list_announcements | ||
responses: | ||
'200': | ||
description: Successful Response | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/Envelope_list_simcore_service_webserver.announcements._models.Announcement__' | ||
components: | ||
schemas: | ||
Announcement: | ||
properties: | ||
id: | ||
type: string | ||
title: Id | ||
products: | ||
items: | ||
type: string | ||
enum: | ||
- osparc | ||
- s4l | ||
- s4llite | ||
- tis | ||
type: array | ||
title: Products | ||
start: | ||
type: string | ||
format: date-time | ||
title: Start | ||
end: | ||
type: string | ||
format: date-time | ||
title: End | ||
title: | ||
type: string | ||
title: Title | ||
description: | ||
type: string | ||
title: Description | ||
link: | ||
type: string | ||
title: Link | ||
widgets: | ||
items: | ||
type: string | ||
enum: | ||
- login | ||
- ribbon | ||
- user-menu | ||
type: array | ||
title: Widgets | ||
type: object | ||
required: | ||
- id | ||
- products | ||
- start | ||
- end | ||
- title | ||
- description | ||
- link | ||
- widgets | ||
title: Announcement | ||
Envelope_list_simcore_service_webserver.announcements._models.Announcement__: | ||
properties: | ||
data: | ||
items: | ||
$ref: '#/components/schemas/Announcement' | ||
type: array | ||
title: Data | ||
error: | ||
title: Error | ||
type: object | ||
title: Envelope[list[simcore_service_webserver.announcements._models.Announcement]] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
""" Helper script to generate OAS automatically | ||
""" | ||
|
||
# pylint: disable=redefined-outer-name | ||
# pylint: disable=unused-argument | ||
# pylint: disable=unused-variable | ||
# pylint: disable=too-many-arguments | ||
|
||
|
||
from enum import Enum | ||
|
||
from fastapi import FastAPI | ||
from models_library.generics import Envelope | ||
from simcore_service_webserver.announcements._handlers import Announcement | ||
|
||
app = FastAPI(redoc_url=None) | ||
|
||
TAGS: list[str | Enum] = [ | ||
"announcements", | ||
] | ||
|
||
|
||
@app.get( | ||
"/announcements", | ||
response_model=Envelope[list[Announcement]], | ||
tags=TAGS, | ||
operation_id="list_announcements", | ||
) | ||
async def list_announcements(): | ||
... | ||
|
||
|
||
if __name__ == "__main__": | ||
from _common import CURRENT_DIR, create_openapi_specs | ||
|
||
create_openapi_specs(app, CURRENT_DIR.parent / "openapi-announcements.yaml") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
# Extra reqs, besides webserver's | ||
|
||
fastapi | ||
fastapi<0.100 | ||
jsonref |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -560,7 +560,7 @@ services: | |
"--loglevel", | ||
"verbose", | ||
"--databases", | ||
"5", | ||
"6", | ||
"--appendonly", | ||
"yes" | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.24.0 | ||
0.25.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
14 changes: 14 additions & 0 deletions
14
services/web/server/src/simcore_service_webserver/announcements/_api.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
""" Service layer with announcement plugin business logic | ||
""" | ||
from aiohttp import web | ||
|
||
from . import _redis | ||
from ._models import Announcement | ||
|
||
|
||
async def list_announcements( | ||
app: web.Application, *, product_name: str | ||
) -> list[Announcement]: | ||
return await _redis.list_announcements( | ||
app, include_product=product_name, exclude_expired=True | ||
) |
22 changes: 22 additions & 0 deletions
22
services/web/server/src/simcore_service_webserver/announcements/_handlers.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
""" Controler layer to expose to the web rest API | ||
""" | ||
from aiohttp import web | ||
|
||
from .._meta import api_version_prefix | ||
from ..products.plugin import get_product_name | ||
from ..utils_aiohttp import envelope_json_response | ||
from . import _api | ||
from ._models import Announcement | ||
|
||
routes = web.RouteTableDef() | ||
|
||
|
||
@routes.get(f"/{api_version_prefix}/announcements", name="list_announcements") | ||
async def list_announcements(request: web.Request) -> web.Response: | ||
"""Returns non-expired announcements for current product""" | ||
product_name = get_product_name(request) | ||
announcements: list[Announcement] = await _api.list_announcements( | ||
request.app, product_name=product_name | ||
) | ||
|
||
return envelope_json_response(announcements) |
58 changes: 58 additions & 0 deletions
58
services/web/server/src/simcore_service_webserver/announcements/_models.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from datetime import datetime | ||
from typing import Any, ClassVar, Literal | ||
|
||
import arrow | ||
from pydantic import BaseModel, validator | ||
|
||
|
||
# NOTE: this model is used for BOTH | ||
# - parse+validate from redis | ||
# - schema in the response | ||
class Announcement(BaseModel): | ||
id: str # noqa: A003 | ||
products: list[str] | ||
start: datetime | ||
end: datetime | ||
title: str | ||
description: str | ||
link: str | ||
widgets: list[Literal["login", "ribbon", "user-menu"]] | ||
|
||
@validator("end") | ||
@classmethod | ||
def check_start_before_end(cls, v, values): | ||
if start := values.get("start"): | ||
end = v | ||
if end <= start: | ||
msg = f"end={end!r} is not before start={start!r}" | ||
raise ValueError(msg) | ||
return v | ||
|
||
def expired(self) -> bool: | ||
return self.end <= arrow.utcnow().datetime | ||
|
||
class Config: | ||
schema_extra: ClassVar[dict[str, Any]] = { | ||
"examples": [ | ||
{ | ||
"id": "Student_Competition_2023", | ||
"products": ["s4llite"], | ||
"start": "2023-06-22T15:00:00.000Z", | ||
"end": "2023-11-01T02:00:00.000Z", | ||
"title": "Student Competition 2023", | ||
"description": "For more information click <a href='https://zmt.swiss/news-and-events/news/sim4life/s4llite-student-competition-2023/' style='color: white' target='_blank'>here</a>", | ||
"link": "https://zmt.swiss/news-and-events/news/sim4life/s4llite-student-competition-2023/", | ||
"widgets": ["login", "ribbon"], | ||
}, | ||
{ | ||
"id": "TIP_v2", | ||
"products": ["tis"], | ||
"start": "2023-07-22T15:00:00.000Z", | ||
"end": "2023-08-01T02:00:00.000Z", | ||
"title": "TIP v2", | ||
"description": "For more information click <a href='https://itis.swiss/tools-and-systems/ti-planning/' style='color: white' target='_blank'>here</a>", | ||
"link": "https://itis.swiss/tools-and-systems/ti-planning/", | ||
"widgets": ["login", "ribbon", "user-menu"], | ||
}, | ||
] | ||
} |
51 changes: 51 additions & 0 deletions
51
services/web/server/src/simcore_service_webserver/announcements/_redis.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
""" Repository layer using redis | ||
""" | ||
|
||
import logging | ||
|
||
import redis.asyncio as aioredis | ||
from aiohttp import web | ||
from pydantic import ValidationError | ||
|
||
from ..redis import get_redis_announcements_client | ||
from ._models import Announcement | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
_PUBLIC_ANNOUNCEMENTS_REDIS_KEY = "public" | ||
# | ||
# At this moment `announcements` are manually stored in redis db 6 w/o guarantees | ||
# Here we validate them and log a big-fat error if there is something wrong | ||
# Invalid announcements are not passed to the front-end | ||
# | ||
_MSG_REDIS_ERROR = f"Invalid announcements[{_PUBLIC_ANNOUNCEMENTS_REDIS_KEY}] in redis. Please check values introduced *by hand*. Skipping" | ||
|
||
|
||
async def list_announcements( | ||
app: web.Application, *, include_product: str, exclude_expired: bool | ||
) -> list[Announcement]: | ||
# get-all | ||
redis_client: aioredis.Redis = get_redis_announcements_client(app) | ||
items: list[str] = await redis_client.lrange(_PUBLIC_ANNOUNCEMENTS_REDIS_KEY, 0, -1) | ||
|
||
# validate | ||
announcements = [] | ||
for i, item in enumerate(items): | ||
try: | ||
model = Announcement.parse_raw(item) | ||
# filters | ||
if include_product not in model.products: | ||
continue | ||
if exclude_expired and model.expired(): | ||
continue | ||
# OK | ||
announcements.append(model) | ||
except ValidationError: # noqa: PERF203 | ||
_logger.exception( | ||
"%s. Check item[%d]=%s", | ||
_MSG_REDIS_ERROR, | ||
i, | ||
item, | ||
) | ||
|
||
return announcements |
Oops, something went wrong.