Skip to content

Commit

Permalink
Merge pull request #51 from redhatcloudx/add-metadata-to-root-route
Browse files Browse the repository at this point in the history
Add metadata to root route
  • Loading branch information
major authored Jul 5, 2024
2 parents f40a74e + 05762be commit 27501c1
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 10 deletions.
3 changes: 2 additions & 1 deletion cid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging

from cid.crud import update_image_data
from cid.crud import update_image_data, update_last_updated
from cid.database import SessionLocal

logger = logging.getLogger(__name__)
Expand All @@ -14,5 +14,6 @@ def populate_db() -> None:

db = SessionLocal()
update_image_data(db)
update_last_updated(db)

logger.info("Database population complete. Exiting.")
21 changes: 19 additions & 2 deletions cid/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

from dateutil import parser
from packaging.version import Version
from sqlalchemy import desc
from sqlalchemy import desc, func
from sqlalchemy.orm import Session
from sqlalchemy.orm.query import Query

from cid.config import CLOUD_PROVIDERS
from cid.database import engine
from cid.models import AwsImage, AzureImage, GoogleImage
from cid.models import AwsImage, AzureImage, GoogleImage, LastUpdate
from cid.utils import (
InvalidCloudProvider,
extract_aws_version,
Expand Down Expand Up @@ -236,6 +236,23 @@ def import_google_images(db: Session, images: list) -> None:
db.commit()


def update_last_updated(db: Session) -> None:
last_update = db.query(LastUpdate).first()
if last_update is None:
last_update = LastUpdate()
db.add(last_update)
else:
last_update.updated_at = func.now()
db.commit()


def get_last_update(db: Session) -> str:
last_update = db.query(LastUpdate).first()
if last_update is None:
return ""
return str(last_update.updated_at)


def update_image_data(db: Session) -> None:
"""Update image data from all cloud providers."""

Expand Down
38 changes: 34 additions & 4 deletions cid/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import logging
import threading
from time import sleep
from typing import Generator, Optional
from typing import Any, Generator, Optional

from fastapi import Depends, FastAPI
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.encoders import jsonable_encoder
from schedule import every, repeat, run_pending
from sqlalchemy.orm import Session
Expand All @@ -26,9 +26,38 @@ def get_db() -> Generator:
db.close()


def check_endpoint_status(
db: Session, endpoint_func: Any, *args: str, **kwargs: int
) -> str:
try:
data = endpoint_func(db, *args, **kwargs)
if data is None:
return "down"
else:
return "running"
except HTTPException:
return "down"


@app.get("/")
def read_root() -> dict:
return {"Hello": "World"}
def read_root(request: Request, db: Session = Depends(get_db)) -> dict: # noqa: B008
aws_status = check_endpoint_status(db, crud.find_aws_images, page=1, page_size=1)
google_status = check_endpoint_status(
db, crud.find_google_images, page=1, page_size=1
)
azure_status = check_endpoint_status(
db, crud.find_azure_images, page=1, page_size=1
)
last_update = crud.get_last_update(db)
return {
"status": {
f"{request.base_url}aws": aws_status,
f"{request.base_url}google": google_status,
f"{request.base_url}azure": azure_status,
},
"docs": f"{request.base_url}docs",
"last_update": last_update,
}


@app.get("/aws")
Expand Down Expand Up @@ -122,6 +151,7 @@ def self_update_image_data() -> None:
"""Update the database with new image data."""
db = SessionLocal()
crud.update_image_data(db)
crud.update_last_updated(db)


def run_schedule() -> None:
Expand Down
9 changes: 8 additions & 1 deletion cid/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Database models."""

from sqlalchemy import JSON, Column, DateTime, Integer, String
from sqlalchemy import JSON, Column, DateTime, Integer, String, func

from cid.database import Base

Expand Down Expand Up @@ -57,3 +57,10 @@ class AzureImage(Base):
sku = Column(String)
urn = Column(String)
version = Column(String)


class LastUpdate(Base):
__tablename__ = "last_update"

id = Column(Integer, primary_key=True)
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
9 changes: 9 additions & 0 deletions tests/test_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
from cid.models import AwsImage, AzureImage, GoogleImage


def test_last_update(db):
result = crud.get_last_update(db)
assert result == ""

crud.update_last_updated(db)
result = crud.get_last_update(db)
assert datetime.strptime(result, "%Y-%m-%d %H:%M:%S")


def test_latest_aws_image_no_images(db):
result = crud.latest_aws_image(db, None)
assert result == {"error": "No images found for AWS.", "code": 404}
Expand Down
35 changes: 33 additions & 2 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import json
from unittest.mock import patch

from fastapi import HTTPException
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from cid import crud
from cid.database import Base
from cid.main import app, get_db
from cid.main import app, check_endpoint_status, get_db

engine = create_engine(
"sqlite:///:memory:", connect_args={"check_same_thread": False}, echo=False
Expand Down Expand Up @@ -48,11 +49,41 @@ def load_test_data():
client = TestClient(app)


def test_check_endpoint_status_running():
def mock_endpoint_func(db, *args, **kwargs):
return "data"

result = check_endpoint_status(None, mock_endpoint_func)
assert result == "running"


def test_check_endpoint_status_down():
def mock_endpoint_func(db, *args, **kwargs):
return None

result = check_endpoint_status(None, mock_endpoint_func)
assert result == "down"


def test_check_endpoint_status_exception():
def mock_endpoint_func(db, *args, **kwargs):
raise HTTPException(status_code=500)

result = check_endpoint_status(None, mock_endpoint_func)
assert result == "down"


def test_read_root():
"""Test the read_root endpoint."""
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"Hello": "World"}
assert response.json()["status"] == {
"http://testserver/aws": "running",
"http://testserver/google": "running",
"http://testserver/azure": "running",
}
assert "docs" in response.json()
assert "last_update" in response.json()


@patch("cid.crud.latest_aws_image")
Expand Down

0 comments on commit 27501c1

Please sign in to comment.