Skip to content

Commit

Permalink
✨ feat(docker logs, bruno, swagger): fixed docker logs duplicated lin…
Browse files Browse the repository at this point in the history
…es bug, added bruno files, added basic swagger functionality
  • Loading branch information
PrtmPhlp committed Dec 5, 2024
1 parent 8f27f74 commit fd53092
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 19 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ Archive/backup/*
log.txt
*/json
docker-fullstack

# Bruno
environments/
!bruno.json
16 changes: 11 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ FROM python:3.12-slim
# Set working directory
WORKDIR /app

# Install curl for healthcheck
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Install curl, cron, and logrotate for healthcheck, scheduling, and log management
RUN apt-get update && apt-get install -y curl cron logrotate && rm -rf /var/lib/apt/lists/*

# Copy requirements first to leverage Docker cache
COPY requirements.txt .
Expand All @@ -21,10 +21,16 @@ COPY schema/ ./schema/
# Create necessary directories and files
RUN mkdir -p json && touch json/scraped.json json/formatted.json

# Add logrotate configuration for your application
RUN echo "/var/log/myapp/*.log {\n size 5M\n rotate 5\n compress\n missingok\n notifempty\n}" > /etc/logrotate.d/myapp

# Add cron job to run logrotate daily
RUN echo "0 0 * * * /usr/sbin/logrotate /etc/logrotate.d/myapp" >> /etc/crontab

# Set environment variables
ENV PYTHONUNBUFFERED=1
# ENV PYTHONUNBUFFERED=1
ENV DSB_USERNAME=""
ENV DSB_PASSWORD=""

# Run the scheduler script
CMD ["python", "src/scheduler.py"]
# Run the scheduler script and cron
CMD cron && python src/scheduler.py
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ urllib3==2.2.2
waitress==3.0.1
Werkzeug==3.0.4
yarl==1.9.4
flask_swagger_ui==4.11.1
36 changes: 28 additions & 8 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
logger = setup_logger(__name__)

app = Flask(__name__)

# TODO: Update CORS origins
CORS(app, resources={r"/*": {"origins": "*"}})

# Setup the Flask-JWT-Extended extension
Expand All @@ -38,6 +40,19 @@
"274583": generate_password_hash("johann")
}

from flask_swagger_ui import get_swaggerui_blueprint

SWAGGER_URL="/swagger"
API_URL="/static/swagger.json"

swagger_ui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': 'Access API'
}
)
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)

def load_json_file():
"""
Expand Down Expand Up @@ -112,11 +127,13 @@ def login():
Returns:
dict: JWT access token or error message.
"""
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
# Check if the request is JSON or form data
if not (request.is_json or request.form):
return jsonify({"msg": "Missing JSON or form data in request"}), 400

username = request.json.get('username', None) # type: ignore[reportOptionalMemberAccess]
password = request.json.get('password', None) # type: ignore[reportOptionalMemberAccess]
# Use form data if available, otherwise fallback to JSON
username = request.form.get('username') if request.form else request.json.get('username', None)
password = request.form.get('password') if request.form else request.json.get('password', None)

if not username or not password:
return jsonify({"msg": "Missing username or password"}), 400
Expand Down Expand Up @@ -195,7 +212,10 @@ def healthcheck():


if __name__ == '__main__':
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
print(f"Server running on http://{local_ip}:5555")
serve(app, host='0.0.0.0', port=5555, _quiet=False)
DEVELOPMENT = True
if DEVELOPMENT:
app.run(host='0.0.0.0', port=5555, debug=True)
else:
local_ip = socket.gethostbyname(socket.gethostname())
print(f"Server running on http://{local_ip}:5555")
serve(app, host='0.0.0.0', port=5555, _quiet=False)
9 changes: 5 additions & 4 deletions src/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ def setup_logger(name: str, level=None) -> logging.Logger:
level=level,
)

#! Logs show duplicate lines in Docker
# Add stdout handler if needed
if not sys.stdout.isatty():
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(level) # Set handler level too
logger.addHandler(handler)
# if not sys.stdout.isatty():
# handler = logging.StreamHandler(sys.stdout)
# handler.setLevel(level) # Set handler level too
# logger.addHandler(handler)

return logger
2 changes: 1 addition & 1 deletion src/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def parse_args() -> argparse.Namespace:
# Ensures raw formatting for the art
formatter_class=RawDescriptionRichHelpFormatter)
parser.add_argument(
"--version", action="version", version="[argparse.prog]%(prog)s[/] version [i]1.1.0[/]"
"--version", action="version", version="[argparse.prog]%(prog)s[/] version [i]1.2.0[/]"
)
parser.add_argument("-v", "--verbose", action="store_true",
help="Set verbosity level to DEBUG")
Expand Down
2 changes: 1 addition & 1 deletion src/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def run_flask_app():
"""Run the Flask application."""
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
print(f"Server running on http://{local_ip}:5555")
print(f"PRODUCTION: Server running on http://{local_ip}:5555")
serve(app.app, host='0.0.0.0', port=5555)


Expand Down
22 changes: 22 additions & 0 deletions tests/api.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
meta {
name: api
type: http
seq: 1
}

get {
url: {{url}}/api/
body: none
auth: bearer
}

auth:bearer {
token: {{token}}
}

tests {
test("Return 200", function() {
const data = res.getBody();
expect(res.getStatus()).to.equal(200);
});
}
9 changes: 9 additions & 0 deletions tests/bruno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1",
"name": "DSBMobile Backend",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
18 changes: 18 additions & 0 deletions tests/healthcheck.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
meta {
name: healthcheck
type: http
seq: 2
}

get {
url: {{url}}/api/healthcheck
body: none
auth: none
}

tests {
test("Return 200", function() {
const data = res.getBody();
expect(res.getStatus()).to.equal(200);
});
}
28 changes: 28 additions & 0 deletions tests/login.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
meta {
name: login
type: http
seq: 3
}

post {
url: {{url}}/login
body: formUrlEncoded
auth: none
}

body:form-urlencoded {
username: {{username}}
password: {{password}}
}

script:post-response {
let data = res.body ;
bru.setEnvVar("token",data.access_token);
}

tests {
test("Return 200", function() {
const data = res.getBody();
expect(res.getStatus()).to.equal(200);
});
}

0 comments on commit fd53092

Please sign in to comment.