feat: update Dockerfile and Makefile for improved deployment; add integration testing instructions and version endpoint
All checks were successful
Build and Push to Private Registry101 / build (push) Successful in 33s
All checks were successful
Build and Push to Private Registry101 / build (push) Successful in 33s
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
__pycache__
|
||||
test.db
|
||||
test*.db
|
||||
.coverage
|
||||
report.xml
|
||||
coverage.xml
|
||||
coverage.xml
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#
|
||||
#
|
||||
|
||||
FROM python:3.12
|
||||
|
||||
@@ -13,4 +15,4 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
||||
|
||||
COPY ./*.py /code/
|
||||
|
||||
CMD ["python3", "papi.py", "--port", "8912"]
|
||||
CMD ["uvicorn", "papi:app","--port", "8912","--host","0.0.0.0"]
|
||||
|
||||
21
Makefile
21
Makefile
@@ -1,20 +1,35 @@
|
||||
ENV=dev
|
||||
VER=4
|
||||
VER=0.0.4
|
||||
TAG=${ENV}-${VER}
|
||||
REGISTRY=kube-reg.fairfaxmedia.net
|
||||
SVC=papi/svc1
|
||||
DOCK_IMG=${REGISTRY}/${SVC}:${TAG}
|
||||
LIVE_HOST:="http://localhost:8912"
|
||||
|
||||
clean:
|
||||
rm -rf .pytest_cache
|
||||
rm -rf .coverage
|
||||
rm -rf report.xml
|
||||
rm -rf test.db
|
||||
rm -rf htmlcov
|
||||
coverage: clean
|
||||
|
||||
install:
|
||||
pip3 install -r requirements.txt
|
||||
coverage: clean install
|
||||
pytest --cov=papi --cov=posts --cov=users test_papi.py test_posts.py test_users.py --junitxml=report.xml --cov-report=html --cov-report=xml --cov-report=term --cov-fail-under 90
|
||||
|
||||
docker-img: coverage
|
||||
docker build -t ${DOCK_IMG} .
|
||||
|
||||
docker-push: docker-img
|
||||
docker push ${DOCK_IMG}
|
||||
|
||||
deploy: docker-push
|
||||
helm upgrade papi ./papi-helm/ -f ./papi-helm/v.${ENV}.yaml --set image.tag=${TAG}
|
||||
helm upgrade papi ./papi-helm/ -f ./papi-helm/v.${ENV}.yaml --set image.tag=${TAG} --set env.VERSION=${VER}
|
||||
integration: install
|
||||
pyresttest ${LIVE_HOST} integration.pyrest.yaml
|
||||
run: install
|
||||
uvicorn papi:app --reload --port 8912 --host 0.0.0.0
|
||||
|
||||
|
||||
all: deploy
|
||||
16
README.md
16
README.md
@@ -72,4 +72,18 @@ ensure you are logged into kubernetes so that commands kubectl and helm both wor
|
||||
then run
|
||||
```bash
|
||||
make deploy
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
##integration testing instructions
|
||||
to test live on papi.kube-dev.fairfaxmedia.net
|
||||
run the following:
|
||||
```bash
|
||||
make integration -e LIVE_HOST=http://papi.kube-dev.fairfaxmedia.net
|
||||
```
|
||||
|
||||
to integration-test on localhost on the default port run
|
||||
```bash
|
||||
make integration
|
||||
```
|
||||
2
db.py
2
db.py
@@ -11,7 +11,7 @@ if os.getenv("DATABASE_URL"):
|
||||
engine = create_engine(DATABASE_URL)
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
Base = declarative_base()
|
||||
|
||||
version = os.environ.get("VERSION", "0.0.0")
|
||||
|
||||
|
||||
|
||||
|
||||
85
integration.pyrest.yaml
Normal file
85
integration.pyrest.yaml
Normal file
@@ -0,0 +1,85 @@
|
||||
# Test using included Django test app
|
||||
# First install python-django
|
||||
# Then launch the app in another terminal by doing
|
||||
# cd testapp
|
||||
# python manage.py testserver test_data.json
|
||||
# Once launched, tests can be executed via:
|
||||
# python resttest.py http://localhost:8000 miniapp-test.yaml
|
||||
---
|
||||
- config:
|
||||
- testset: "Tests using test app"
|
||||
- variable_binds:
|
||||
- 'uid': 1
|
||||
- 'post_id': 1
|
||||
|
||||
- test: # create entity
|
||||
- name: "Basic get"
|
||||
- url: "/"
|
||||
- test: # create entity
|
||||
- name: "Get version"
|
||||
- url: "/version"
|
||||
|
||||
|
||||
- test: # create person by POST
|
||||
- name: "Create person"
|
||||
- url: "/users"
|
||||
- method: "POST"
|
||||
- body: '{"name": "Willim","email": "theadmiral@gmail.com"}'
|
||||
- headers: {Content-Type: application/json}
|
||||
- extract_binds:
|
||||
- 'uid' : {'jsonpath_mini': "user.id"}
|
||||
|
||||
- test: # get single person
|
||||
- name: "Get single person"
|
||||
- url: {'template':'/users/$uid'} # use binded value
|
||||
- method: 'GET'
|
||||
|
||||
- test: # update person by PUT
|
||||
- name: "update person by PUT"
|
||||
- url: {'template':'/users/$uid'}
|
||||
- method: "PUT"
|
||||
- body: '{"name": "Gaius"}'
|
||||
- headers: {'Content-Type': 'application/json'}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- test: # create post by POST
|
||||
- name: "Create post"
|
||||
- url: "/posts"
|
||||
- method: "POST"
|
||||
- body: '{"title": "Willims post","content": "william made a post","author_id": 1}'
|
||||
- headers: {Content-Type: application/json}
|
||||
- extract_binds:
|
||||
- 'post_id' : {'jsonpath_mini': "post.id"}
|
||||
|
||||
- test: # get single post
|
||||
- name: "Get single post"
|
||||
- url: {'template':'/posts/$post_id'}
|
||||
- method: 'GET'
|
||||
|
||||
- test: # update post by PUT
|
||||
- name: "update post by PUT"
|
||||
- url: {'template':'/posts/$post_id'}
|
||||
- method: "PUT"
|
||||
- body: '{"title": "Gaius made a post"}'
|
||||
- headers: {'Content-Type': 'application/json'}
|
||||
- test: # delete post
|
||||
- name: "Delete post"
|
||||
- url: {'template':'/posts/$post_id'}
|
||||
- method: "DELETE"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- test: # delete person
|
||||
- name: "Delete person"
|
||||
- url: {'template':'/users/$uid'}
|
||||
- method: "DELETE"
|
||||
|
||||
|
||||
|
||||
17
papi.py
17
papi.py
@@ -1,4 +1,11 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
# author: Stephen Schuresko
|
||||
# date: 2025-02-18
|
||||
# file: papi.py
|
||||
# description: A simple FastAPI app (papi) with a few routes and models for users and posts
|
||||
#
|
||||
|
||||
from fastapi import FastAPI, Depends
|
||||
import uvicorn
|
||||
from sqlalchemy import create_engine, Column, Integer,String, ForeignKey
|
||||
@@ -7,6 +14,7 @@ from sqlalchemy.orm import sessionmaker, Session, declarative_base
|
||||
import db
|
||||
import users
|
||||
import posts
|
||||
import os
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +27,6 @@ app.include_router(posts.router)
|
||||
async def root():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run("papi:app", host="0.0.0.0", port=8912, reload=True, log_level="debug",
|
||||
workers=5, limit_concurrency=10, limit_max_requests=100)
|
||||
|
||||
@app.get("/version")
|
||||
async def ver():
|
||||
return {"version":db.version}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
fastapi
|
||||
sqlalchemy
|
||||
uvicorn
|
||||
pyresttest
|
||||
@@ -12,3 +12,10 @@ def test_read_main():
|
||||
assert response.json() == {"message": "Hello World"}
|
||||
|
||||
|
||||
|
||||
|
||||
def test_read_version():
|
||||
response = client.get("/version")
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user