Git implementation and Swagger

oggit
Vadim vtroshchinskiy 2025-04-28 11:39:19 +02:00
parent c23b4ddddb
commit f055aaf69d
2 changed files with 677 additions and 45 deletions

View File

@ -48,6 +48,19 @@ trash_file = '/opt/opengnsys/ogrepository/etc/trashinfo.json'
config_file = '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'
# --------------------------------------------------------------------------------------------
# GIT
# --------------------------------------------------------------------------------------------
REPOSITORIES_BASE_PATH = "/opt/opengnsys/ogrepository/oggit/git/oggit/"
import git
import pkgutil
import importlib
# --------------------------------------------------------------------------------------------
# FUNCTIONS
# --------------------------------------------------------------------------------------------
@ -2185,6 +2198,329 @@ def rename_image():
# -----------------------------------------------------------
# ____ _ _
# / ___(_) |_
# | | _| | __|
# | |_| | | |_
# \____|_|\__|
#
# -----------------------------------------------------------
@app.route("/ogrepository/v1/git/repositories", methods=['GET'])
def git_list_repositories():
"""
Retrieve a list of Git repositories.
This endpoint scans the OpenGnsys image path for directories that
appear to be Git repositories (i.e., they contain a "HEAD" file).
It returns a JSON response containing the names of these repositories.
Returns:
Response: A JSON response with a list of repository names or an
error message if the repository storage is not found.
- 200 OK: When the repositories are successfully retrieved.
- 500 Internal Server Error: When the repository storage is not found.
Example JSON response:
{
"repositories": ["repo1", "repo2"]
}
"""
journal.send("Running endpoint 'Obtener Información de todos los repositorios Git'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
if not os.path.isdir(REPOSITORIES_BASE_PATH):
journal.send(f"Can't list repositories. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Repository storage not found, git functionality may not be installed."}), 500
repos = []
for entry in os.scandir(REPOSITORIES_BASE_PATH):
if entry.is_dir(follow_symlinks=False) and os.path.isfile(os.path.join(entry.path, "HEAD")):
name = entry.name
if name.endswith(".git"):
name = name[:-4]
repos = repos + [name]
journal.send(f"Returning {len(repos)} repositories", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({
"repositories": repos
}), 200
def _load_module(module_name):
import importlib
return importlib.util.find_spec(module_name) is not None
return False
def _load_installer():
return _load_module("opengnsys-git-installer")
@app.route("/ogrepository/v1/git/repositories", methods=['POST'])
def git_create_repository():
"""
Create a new Git repository.
This endpoint creates a new Git repository with the specified name.
If the repository already exists, it returns a status message indicating so.
Args:
repo (str): The name of the repository to be created.
Returns:
Response: A JSON response with a status message and HTTP status code.
- 200: If the repository already exists.
- 201: If the repository is successfully created.
"""
data = request.json
if data is None:
journal.send(f"Can't create repository, JSON post data missing", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error" : "Parameters missing"}), 400
repo = data["name"]
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if os.path.isdir(repo_path):
journal.send(f"Can't create repository {repo}, already exists at {repo_path}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "Repository already exists"}), 200
_import_installer()
installer = OpengnsysGitInstaller()
installer.add_forgejo_repo(repo)
journal.send(f"Repository {repo} created", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "Repository created"}), 201
@app.route("/ogrepository/v1/git/repositories", methods=['DELETE'])
def git_delete_repository():
return jsonify({"error" : "Not implemented"}), 500
@app.route("/ogrepository/v1/git/repositories/<string:repo>/sync", methods=['POST'])
def git_sync_repository(repo):
return jsonify({"error" : "Not implemented"}), 500
@app.route("/ogrepository/v1/git/repositories/<string:repo>/backup", methods=['POST'])
def git_backup_repository(repo):
return jsonify({"error" : "Not implemented"}), 500
@app.route("/ogrepository/v1/git/repositories/<string:repo>/compact", methods=['POST'])
def git_compact_repository(repo):
return jsonify({"error" : "Not implemented"}), 500
@app.route("/ogrepository/v1/git/repositories/<string:repo>/branches", methods=['GET'])
def git_get_branches(repo):
"""
Retrieve the list of branches for a given repository.
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a list of branch names or an error message if the repository is not found.
- 200: A JSON object with a "branches" key containing a list of branch names.
- 404: A JSON object with an "error" key containing the message "Repository not found" if the repository does not exist.
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't list repositories. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Repository not found"}), 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
branches = []
for branch in git_repo.branches:
branches = branches + [branch.name]
journal.send(f"Returning {len(branches)} branches", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return {
"branches": branches
}
@app.route("/ogrepository/v1/git/repositories/<string:repo>/branches/<string:branch>", methods=['POST'])
def git_create_branch(repo, branch):
"""Create a given branch in a given repository
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a creation status
- 201: A JSON object with a "status" key containing "created"
- 404: A JSON object with an "error" key containing the message "Repository not found"
- 409: A JSON object with an "error" key containing the message "Tag already exists"
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't create branch. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Repository not found"}), 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
data = request.json
if data is None:
journal.send(f"Can't create branch. JSON post data missing", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error" : "Parameters missing"}), 400
if not "commit" in data:
journal.send(f"Can't create branch. Commit parameter missing", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error" : "commit parameter missing"}), 400
if branch in git_repo.branches:
journal.send(f"Can't create branch. Already found in repository {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Branch already exists"}), 409
git_repo.create_tag(branch, ref = data["commit"])
journal.send(f"Branch {branch} created in repo {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "created"}), 201
@app.route("/ogrepository/v1/git/repositories/<string:repo>/branches/<string:branch>", methods=['DELETE'])
def git_delete_branch(repo, branch):
"""Delete a given branch in a given repository
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a list of branch names or an error message if the repository is not found.
- 200: A JSON object with a "status" key containing "deleted"
- 404: A JSON object with an "error" key containing the message "Repository not found" or "Branch not found"
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't delete branch. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return {"error": "Repository not found"}, 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
if not branch in git_repo.branches:
journal.send(f"Can't delete branch. Not found in repository {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Branch not found"}), 404
git_repo.delete_head(branch)
journal.send(f"Branch {branch} deleted in repo {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "deleted"}), 200
@app.route("/ogrepository/v1/git/repositories/<string:repo>/tags", methods=['GET'])
def git_list_tags(repo):
"""
Retrieve the list of tags for a given repository.
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a list of tag names or an error message if the repository is not found.
- 200: A JSON object with a "branches" key containing a list of tag names.
- 404: A JSON object with an "error" key containing the message "Repository not found" if the repository does not exist.
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't list repositories. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Repository not found"}), 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
tags = []
for tag in git_repo.tags:
tags = tags + [tag.name]
journal.send(f"Returning {len(tags)} branches", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return {
"tags": tags
}
@app.route("/ogrepository/v1/git/repositories/<string:repo>/tags/<string:tag>", methods=['POST'])
def git_create_tag(repo, tag):
"""Create a given tag in a given repository
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a creation status
- 200: A JSON object with a "status" key containing "created"
- 404: A JSON object with an "error" key containing the message "Repository not found"
- 409: A JSON object with an "error" key containing the message "Tag already exists"
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't create tag. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Repository not found"}), 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
data = request.json
if data is None:
journal.send(f"Can't create tag. JSON post data missing", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error" : "Parameters missing"}), 400
if not "commit" in data:
journal.send(f"Can't create tag. Commit parameter missing", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error" : "commit parameter missing"}), 400
if tag in git_repo.tags:
journal.send(f"Can't create tag. Already found in repository {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Tag already exists"}), 409
git_repo.create_tag(tag, ref = data["commit"])
journal.send(f"Tag {tag} created in repo {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "created"}), 200
@app.route("/ogrepository/v1/git/repositories/<string:repo>/tags/<string:tag>", methods=['DELETE'])
def git_delete_tag(repo, tag):
"""Delete a given tag in a given repository
Args:
repo (str): The name of the repository.
Returns:
Response: A JSON response containing a list of tag names or an error message if the repository is not found.
- 200: A JSON object with a "status" key containing "deleted"
- 404: A JSON object with an "error" key containing the message "Repository not found" or "Tag not found"
"""
repo_path = os.path.join(REPOSITORIES_BASE_PATH, repo + ".git")
if not os.path.isdir(repo_path):
journal.send(f"Can't delete tag. Repository storage at {REPOSITORIES_BASE_PATH} not found", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return {"error": "Repository not found"}, 404
git_repo = git.Repo(repo_path)
git_repo.git.config('--global', '--add', 'safe.directory', repo_path)
if not tag in git_repo.tags:
journal.send(f"Can't delete tag. Not found in repository {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"error": "Tag not found"}), 404
git_repo.delete_head(tag)
journal.send(f"Tag {tag} deleted in repo {repo}", PRIORITY=journal.LOG_ERROR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
return jsonify({"status": "deleted"}), 200
# --------------------------------------------------------------------------------------------

View File

@ -18,7 +18,7 @@ tags:
- name: "Transferencia entre Repositorios y Backup"
- name: "Importar y Exportar Máquinas Virtuales"
- name: "Varios"
- name: "Git"
# -----------------------------------------------------------------------------------------------------------
# Apartado "Estado de ogRepository"
@ -1960,3 +1960,299 @@ paths:
example: "(Exception description)"
# -----------------------------------------------------------------------------------------------------------
# -----------------------------------------------------------
# ____ _ _
# / ___(_) |_
# | | _| | __|
# | |_| | | |_
# \____|_|\__|
#
# -----------------------------------------------------------
/ogrepository/v1/git/repositories:
get:
summary: "Obtener lista de repositorios"
description: |
Devuelve una lista de repositorios de Git
tags:
- "Git"
parameters:
responses:
"200":
description: "Lista de repositorios"
schema:
type: array
items:
type: string
example: linux
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
post:
summary: "Crear repositorio"
description: |
Crea un repositorio nuevo de Git
tags:
- "Git"
parameters:
- name: JSON
in: body
required: true
description: |
* **name** - Nombre de repositorio
schema:
type: object
properties:
name:
type: string
example: linux
responses:
"201":
description: "Repositorio creado"
schema:
type: object
properties:
status:
type: string
example: "Repository created"
"500 (Exception)":
description: "JSON post data missing"
schema:
type: object
properties:
error:
type: string
example: "Parameters missing"
/ogrepository/v1/git/tags:
get:
summary: "Obtener lista de tags"
description: |
Devuelve una lista de tags de Git
tags:
- "Git"
parameters:
responses:
"200":
description: "Lista de tags"
schema:
type: array
items:
type: string
example: v0.1
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
/ogrepository/v1/git/tags/{branchId}:
post:
summary: "Crear tag"
description: |
Crea una tag de git
tags:
- "Git"
parameters:
- name: JSON
in: body
required: true
description: |
* **commit** - Commit al que apunta el tag nuevo. Puede ser un nombre de otra rama/tag.
schema:
type: object
properties:
name:
type: string
example: HEAD
responses:
"201":
description: "Tag creado"
schema:
type: object
properties:
status:
type: string
example: created
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
"404":
description: "El repositorio no existe"
schema:
type: object
properties:
error:
type: string
example: "Repository not found"
"409":
description: "El tag ya existe"
schema:
type: object
properties:
error:
type: string
example: "Tag already exists"
delete:
summary: "Eliminar tag"
description: |
Elimina un tag de git
tags:
- "Git"
parameters:
responses:
"200":
description: "Tag eliminado"
schema:
type: object
properties:
status:
type: string
example: deleted
"500":
description: "Git no instalado"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
/ogrepository/v1/git/branches:
get:
summary: "Obtener lista de branches"
description: |
Devuelve una lista de branches de Git
tags:
- "Git"
parameters:
responses:
"200":
description: "Lista de branches"
schema:
type: array
items:
type: string
example: main
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
"404":
description: "El repositorio no existe"
schema:
type: object
properties:
error:
type: string
example: "Repository not found"
"409":
description: "El branch ya existe"
schema:
type: object
properties:
error:
type: string
example: "Branch already exists"
/ogrepository/v1/git/branches/{branchId}:
post:
summary: "Crear branch"
description: |
Crea una rama de git
tags:
- "Git"
parameters:
- name: JSON
in: body
required: true
description: |
* **commit** - Commit al que apunta la rama nueva. Puede ser un nombre de otra rama/tag.
schema:
type: object
properties:
name:
type: string
example: HEAD
responses:
"201":
description: "Rama creada"
schema:
type: array
items:
type: string
example: main
"500":
description: "Git no instalado"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"
delete:
summary: "Eliminar branch"
description: |
Elimina una rama de git
tags:
- "Git"
parameters:
responses:
"200":
description: "Branch eliminado"
schema:
type: object
properties:
status:
type: string
example: deleted
"500":
description: "Excepción"
schema:
type: object
properties:
success:
type: boolean
example: false
exception:
type: string
example: "(Exception description)"