Improvements for logging and error handling
parent
14cd2d4363
commit
73118501b3
|
@ -59,6 +59,16 @@ from flask_executor import Executor
|
|||
from flask_restx import Api, Resource, fields
|
||||
#from flasgger import Swagger
|
||||
import paramiko
|
||||
import logging
|
||||
from systemd.journal import JournalHandler
|
||||
|
||||
debug_enabled = False
|
||||
|
||||
log = logging.getLogger('gitapi')
|
||||
log.addHandler(JournalHandler())
|
||||
log.setLevel(logging.INFO)
|
||||
log.info("Started")
|
||||
|
||||
|
||||
REPOSITORIES_BASE_PATH = "/opt/opengnsys/ogrepository/oggit/git/oggit/"
|
||||
|
||||
|
@ -158,6 +168,35 @@ def do_repo_gc(repo):
|
|||
return True
|
||||
|
||||
|
||||
@app.errorhandler(Exception)
|
||||
def handle_exception(e):
|
||||
"""Return JSON for errors"""
|
||||
# start with the correct headers and status code from the error
|
||||
response = e.get_response()
|
||||
|
||||
errid = uuid.uuid4()
|
||||
|
||||
|
||||
if debug_enabled:
|
||||
response = {
|
||||
"errcode": e.code,
|
||||
"errname": e.name,
|
||||
"description": e.description,
|
||||
}
|
||||
else:
|
||||
response = {
|
||||
"errcode" : 500,
|
||||
"errname" : "Internal error",
|
||||
"description": f"Please see the log for error {errid}",
|
||||
"error_id" : errid
|
||||
}
|
||||
|
||||
log.error("Error ID %s: code %i, name %s, description %s", errid, e.code, e.name, e.description, extra = { "error_id" : errid, "errcode" : e.code, "errname" : e.name, "description" : e.description })
|
||||
|
||||
# response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
# Define a route for the root URL
|
||||
@api.route('/')
|
||||
class GitLib(Resource):
|
||||
|
@ -170,6 +209,8 @@ class GitLib(Resource):
|
|||
Returns:
|
||||
Response: A Flask JSON response containing a welcome message.
|
||||
"""
|
||||
log.info("Root URL accessed")
|
||||
|
||||
return {
|
||||
"message": "OpenGnsys Git API"
|
||||
}
|
||||
|
@ -197,6 +238,7 @@ class GitRepositories(Resource):
|
|||
"""
|
||||
|
||||
if not os.path.isdir(REPOSITORIES_BASE_PATH):
|
||||
log.error("Can't list repositories. Repository storage at %s not found", REPOSITORIES_BASE_PATH, extra = {"path" : REPOSITORIES_BASE_PATH})
|
||||
return {"error": "Repository storage not found, git functionality may not be installed."}, 500
|
||||
|
||||
repos = []
|
||||
|
@ -208,6 +250,7 @@ class GitRepositories(Resource):
|
|||
|
||||
repos = repos + [name]
|
||||
|
||||
log.info("Returning %i repositories", len(repos))
|
||||
return {
|
||||
"repositories": repos
|
||||
}
|
||||
|
@ -236,6 +279,7 @@ class GitRepositories(Resource):
|
|||
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if os.path.isdir(repo_path):
|
||||
log.error("Can't create repository %s, already exists at %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path})
|
||||
return {"status": "Repository already exists"}, 200
|
||||
|
||||
|
||||
|
@ -244,7 +288,7 @@ class GitRepositories(Resource):
|
|||
|
||||
#installer.init_git_repo(repo + ".git")
|
||||
|
||||
|
||||
log.info("Repository %s created", repo, extra = {"repository" : repo})
|
||||
return {"status": "Repository created"}, 201
|
||||
|
||||
|
||||
|
@ -268,6 +312,7 @@ class GitRepoSync(Resource):
|
|||
"""
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if not os.path.isdir(repo_path):
|
||||
log.error("Can't sync repository %s, not found. Looked in %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path })
|
||||
return {"error": "Repository not found"}, 404
|
||||
|
||||
|
||||
|
@ -276,9 +321,15 @@ class GitRepoSync(Resource):
|
|||
if data is None:
|
||||
return {"error" : "Parameters missing"}, 400
|
||||
|
||||
if not "remote_repository" in data:
|
||||
return {"error" : "Parameter 'remote_repository' missing"}, 400
|
||||
|
||||
|
||||
future = executor.submit(do_repo_sync, repo, data)
|
||||
task_id = str(uuid.uuid4())
|
||||
tasks[task_id] = future
|
||||
|
||||
log.info("Starting synchronization of repository %s, task %s", repo, task_id, extra = {"repository" : repo, "task_id" : task_id})
|
||||
return {"status": "started", "task_id" : task_id}, 200
|
||||
|
||||
|
||||
|
@ -310,6 +361,7 @@ class GitRepoBackup(Resource):
|
|||
"""
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if not os.path.isdir(repo_path):
|
||||
log.error("Can't backup repository %s, not found. Looked in %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path })
|
||||
return {"error": "Repository not found"}, 404
|
||||
|
||||
|
||||
|
@ -326,6 +378,7 @@ class GitRepoBackup(Resource):
|
|||
task_id = str(uuid.uuid4())
|
||||
tasks[task_id] = future
|
||||
|
||||
log.info("Starting backup of repository %s, task %s", repo, task_id, extra = {"repository" : repo, "task_id" : task_id})
|
||||
return {"status": "started", "task_id" : task_id}, 200
|
||||
|
||||
@git_ns.route('/repositories/<repo>/compact', methods=['POST'])
|
||||
|
@ -348,12 +401,14 @@ class GitRepoCompact(Resource):
|
|||
"""
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if not os.path.isdir(repo_path):
|
||||
log.error("Can't compact repository %s, not found. Looked in %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path })
|
||||
return {"error": "Repository not found"}, 404
|
||||
|
||||
future = executor.submit(do_repo_gc, repo)
|
||||
task_id = str(uuid.uuid4())
|
||||
tasks[task_id] = future
|
||||
|
||||
log.info("Starting compaction of repository %s, task %s", repo, task_id, extra = {"repository" : repo, "task_id" : task_id})
|
||||
return {"status": "started", "task_id" : task_id}, 200
|
||||
|
||||
|
||||
|
@ -373,14 +428,17 @@ class GitTaskStatus(Resource):
|
|||
- If the task is still in progress, returns a 202 status indicating the task is in progress.
|
||||
"""
|
||||
if not task_id in tasks:
|
||||
log.error("Task %s was not found", task_id, extra = {"task_id" : task_id})
|
||||
return {"error": "Task not found"}, 404
|
||||
|
||||
future = tasks[task_id]
|
||||
|
||||
if future.done():
|
||||
result = future.result()
|
||||
log.info("Returning completion of task %s", task_id, extra = {"task_id" : task_id})
|
||||
return {"status" : "completed", "result" : result}, 200
|
||||
else:
|
||||
log.info("Task %s is still in progress", task_id, extra = {"task_id" : task_id})
|
||||
return {"status" : "in progress"}, 202
|
||||
|
||||
|
||||
|
@ -405,10 +463,12 @@ class GitRepo(Resource):
|
|||
"""
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if not os.path.isdir(repo_path):
|
||||
log.error("Can't delete repository %s, not found. Looked in %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path })
|
||||
return {"error": "Repository not found"}, 404
|
||||
|
||||
|
||||
shutil.rmtree(repo_path)
|
||||
log.info("Deleted repository %s", repo, extra = {"repository" : repo})
|
||||
return {"status": "Repository deleted"}, 200
|
||||
|
||||
|
||||
|
@ -430,6 +490,7 @@ class GitRepoBranches(Resource):
|
|||
"""
|
||||
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
|
||||
if not os.path.isdir(repo_path):
|
||||
log.error("Can't get branches of repository repository %s, not found. Looked in %s", repo, repo_path, extra = {"repository" : repo, "path" : repo_path })
|
||||
return {"error": "Repository not found"}, 404
|
||||
|
||||
git_repo = git.Repo(repo_path)
|
||||
|
@ -438,7 +499,7 @@ class GitRepoBranches(Resource):
|
|||
for branch in git_repo.branches:
|
||||
branches = branches + [branch.name]
|
||||
|
||||
|
||||
log.info("Returning %i branches", len(branches))
|
||||
return {
|
||||
"branches": branches
|
||||
}
|
||||
|
@ -460,6 +521,7 @@ class GitHealth(Resource):
|
|||
active and functional.
|
||||
|
||||
"""
|
||||
log.info("Health check endpoint called")
|
||||
return {
|
||||
"status": "OK"
|
||||
}
|
||||
|
@ -476,6 +538,8 @@ class GitStatus(Resource):
|
|||
Response: A JSON response with status information
|
||||
|
||||
"""
|
||||
log.info("Status endpoint called")
|
||||
|
||||
return {
|
||||
"uptime" : time.time() - start_time,
|
||||
"active_tasks" : len(tasks)
|
||||
|
|
Loading…
Reference in New Issue