This commit is contained in:
		
							
								
								
									
										36
									
								
								mealAPI/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								mealAPI/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from flask import Flask
 | 
			
		||||
from flask_restful import Api
 | 
			
		||||
from healthcheck import HealthCheck
 | 
			
		||||
from utils import Config, register_all_error_handlers, health_database_status
 | 
			
		||||
from model import db
 | 
			
		||||
from schemas import ma
 | 
			
		||||
from resources import MealBaseResource
 | 
			
		||||
 | 
			
		||||
app = Flask(__name__)
 | 
			
		||||
app.config.from_object(Config)
 | 
			
		||||
 | 
			
		||||
api = Api(app)
 | 
			
		||||
health = HealthCheck()
 | 
			
		||||
ma.init_app(app)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.before_first_request
 | 
			
		||||
def init_db():
 | 
			
		||||
    db.create_all()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
api.add_resource(MealBaseResource, "/meals")
 | 
			
		||||
 | 
			
		||||
health.add_check(health_database_status)
 | 
			
		||||
 | 
			
		||||
register_all_error_handlers(app)
 | 
			
		||||
 | 
			
		||||
app.add_url_rule("/healthz", "healthcheck", view_func=lambda: health.run())
 | 
			
		||||
 | 
			
		||||
if __name__ != '__main__':
 | 
			
		||||
    import logging
 | 
			
		||||
 | 
			
		||||
    gunicorn_logger = logging.getLogger('gunicorn.error')
 | 
			
		||||
    app.logger.handlers = gunicorn_logger.handlers
 | 
			
		||||
    app.logger.setLevel(gunicorn_logger.level)
 | 
			
		||||
							
								
								
									
										3
									
								
								mealAPI/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mealAPI/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from .db import db
 | 
			
		||||
from .meal import Meal
 | 
			
		||||
from .ingredient import Ingredient
 | 
			
		||||
							
								
								
									
										4
									
								
								mealAPI/model/db.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mealAPI/model/db.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from flask_sqlalchemy import SQLAlchemy
 | 
			
		||||
 | 
			
		||||
db = SQLAlchemy()
 | 
			
		||||
							
								
								
									
										11
									
								
								mealAPI/model/ingredient.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								mealAPI/model/ingredient.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from .db import db
 | 
			
		||||
from .mealingredient import MealIngredient
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Ingredient(db.Model):
 | 
			
		||||
    __tablename__ = 'Ingredient'
 | 
			
		||||
    id = db.Column(db.Integer, primary_key=True)
 | 
			
		||||
    name = db.Column(db.String, nullable=False, unique=True)
 | 
			
		||||
    value = db.Column(db.String, nullable=False)
 | 
			
		||||
    items = db.relationship('Meal', secondary=MealIngredient, back_populates='Ingredient')
 | 
			
		||||
							
								
								
									
										16
									
								
								mealAPI/model/meal.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								mealAPI/model/meal.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from .db import db
 | 
			
		||||
from .mealingredient import MealIngredient
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Meal(db.Model):
 | 
			
		||||
    __tablename__ = 'Meal'
 | 
			
		||||
    id = db.Column(db.Integer, primary_key=True)
 | 
			
		||||
    name = db.Column(db.String(255), nullable=False)
 | 
			
		||||
    description = db.Column(db.Text, nullable=False)
 | 
			
		||||
    kcal = db.Column(db.Integer, nullable=True)
 | 
			
		||||
    price = db.Column(db.Integer, nullable=True)
 | 
			
		||||
    spicy = db.Column(db.Boolean, nullable=False, default=False)
 | 
			
		||||
    vegan = db.Column(db.Boolean, nullable=False, default=False)
 | 
			
		||||
    glutenfree = db.Column(db.Boolean, nullable=False, default=False)
 | 
			
		||||
    ingredients = db.relationship('Ingredient', secondary=MealIngredient, back_populates='Meal')
 | 
			
		||||
							
								
								
									
										9
									
								
								mealAPI/model/mealingredient.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								mealAPI/model/mealingredient.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from .db import db
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MealIngredient(db.Model):
 | 
			
		||||
    __tablename__ = 'MealIngredient'
 | 
			
		||||
    id = db.Column(db.Integer, primary_key=True, index=True)
 | 
			
		||||
    itemId = db.Column(db.Integer, db.ForeignKey('Meal.id'))
 | 
			
		||||
    detailId = db.Column(db.Integer, db.ForeignKey('Ingredient.id'))
 | 
			
		||||
							
								
								
									
										1
									
								
								mealAPI/resources/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								mealAPI/resources/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
from .mealresource import MealBaseResource
 | 
			
		||||
							
								
								
									
										28
									
								
								mealAPI/resources/mealresource.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mealAPI/resources/mealresource.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from flask_restful import Resource
 | 
			
		||||
from flask import request, current_app, abort
 | 
			
		||||
from marshmallow import ValidationError
 | 
			
		||||
 | 
			
		||||
from ..model import db, Meal
 | 
			
		||||
from ..schemas import MealSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MealBaseResource(Resource):
 | 
			
		||||
 | 
			
		||||
    mealschema = MealSchema(many=False)
 | 
			
		||||
    mealschemas = MealSchema(many=True)
 | 
			
		||||
 | 
			
		||||
    def post(self):
 | 
			
		||||
        body = request.get_json()
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            mealobj = self.mealschema.load(body)
 | 
			
		||||
            db.session.add(mealobj.data)
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
            return '', 204
 | 
			
		||||
        except ValidationError:
 | 
			
		||||
            abort(406, "meal validation error")
 | 
			
		||||
 | 
			
		||||
    def get(self):
 | 
			
		||||
        meals = Meal.query.all()
 | 
			
		||||
        return self.mealschemas.dump(list(meals)), 200
 | 
			
		||||
							
								
								
									
										3
									
								
								mealAPI/schemas/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mealAPI/schemas/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from .marshm import ma
 | 
			
		||||
from .mealschema import MealSchema
 | 
			
		||||
from .ingredientschema import IngredientSchema
 | 
			
		||||
							
								
								
									
										9
									
								
								mealAPI/schemas/ingredientschema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								mealAPI/schemas/ingredientschema.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from .marshm import ma
 | 
			
		||||
from ..model import Ingredient
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IngredientSchema(ma.ModelSchema):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Ingredient
 | 
			
		||||
							
								
								
									
										5
									
								
								mealAPI/schemas/marshm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								mealAPI/schemas/marshm.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
from flask_marshmallow import Marshmallow
 | 
			
		||||
 | 
			
		||||
ma = Marshmallow()
 | 
			
		||||
							
								
								
									
										13
									
								
								mealAPI/schemas/mealschema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								mealAPI/schemas/mealschema.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
from .marshm import ma
 | 
			
		||||
from ..model import Meal
 | 
			
		||||
from .ingredientschema import IngredientSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MealSchema(ma.ModelSchema):
 | 
			
		||||
 | 
			
		||||
    # A list of author objects
 | 
			
		||||
    authors = ma.Nested(IngredientSchema, many=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Meal
 | 
			
		||||
							
								
								
									
										3
									
								
								mealAPI/utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mealAPI/utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from .config import Config
 | 
			
		||||
from .error_handlers import register_all_error_handlers
 | 
			
		||||
from .healthchecks import health_database_status
 | 
			
		||||
							
								
								
									
										11
									
								
								mealAPI/utils/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								mealAPI/utils/config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Config:
 | 
			
		||||
    PORT = 8080
 | 
			
		||||
    DEBUG = os.environ.get("INPUT_SERVICE_DEBUG", "true").lower() in ["true", "yes", "1"]
 | 
			
		||||
 | 
			
		||||
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI')
 | 
			
		||||
    # disable this for better performance
 | 
			
		||||
    SQLALCHEMY_TRACK_MODIFICATIONS = False
 | 
			
		||||
							
								
								
									
										18
									
								
								mealAPI/utils/error_handlers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								mealAPI/utils/error_handlers.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_standard_error_handler(code: int):
 | 
			
		||||
    def error_handler(err):
 | 
			
		||||
        return {"msg": str(err)}, code
 | 
			
		||||
 | 
			
		||||
    return error_handler
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# function to register all handlers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def register_all_error_handlers(app):
 | 
			
		||||
    error_codes_to_override = [404, 403, 401, 405, 400, 409, 422, 500]
 | 
			
		||||
 | 
			
		||||
    for code in error_codes_to_override:
 | 
			
		||||
        app.register_error_handler(code, get_standard_error_handler(code))
 | 
			
		||||
							
								
								
									
										14
									
								
								mealAPI/utils/healthchecks.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								mealAPI/utils/healthchecks.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
from model import db
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def health_database_status():
 | 
			
		||||
    is_database_working = True
 | 
			
		||||
    output = 'database is ok'
 | 
			
		||||
    try:
 | 
			
		||||
        db.session.execute('SELECT 1')
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        output = str(e)
 | 
			
		||||
        is_database_working = False
 | 
			
		||||
    return is_database_working, output
 | 
			
		||||
		Reference in New Issue
	
	Block a user