From cc66026ee38265210b9fdaaf3096e8564e006799 Mon Sep 17 00:00:00 2001
From: Daniel Nemergut <dnemergu@nrao.edu>
Date: Thu, 30 May 2024 22:42:01 -0400
Subject: [PATCH] Added casa matrix routes, not sure if this should stay in the
 capability service but we shall see

---
 docs/swagger-schema.yaml                      | 161 ++++++++++++++++++
 services/capability/capability/routes.py      |  20 +++
 .../capability/capability/views/capability.py | 130 +++++++++++++-
 3 files changed, 310 insertions(+), 1 deletion(-)

diff --git a/docs/swagger-schema.yaml b/docs/swagger-schema.yaml
index c35a228b9..16343c663 100644
--- a/docs/swagger-schema.yaml
+++ b/docs/swagger-schema.yaml
@@ -622,6 +622,124 @@ paths:
           description: "successful operation"
           schema:
             type: integer
+  /casa_matrix/get_casa)version:
+    parameters:
+      - $ref: "#/parameters/casa-version"
+      - $ref: "#/parameters/casa-capability"
+      - $ref: "#/parameters/casa-telescope"
+    get:
+      tags:
+        - "casa-matrix"
+      summary: "Get a valid CASA version for processing"
+      description: "Get a valid CASA version for processing, providing the optional parameters will filter the version"
+      operationId: "get_casa_version"
+      responses:
+        404:
+          description: "No CASA version found"
+        200:
+          description: "successful operation"
+          schema:
+            $ref: "#/definitions/CasaVersion"
+  /casa_matrix/get_casa_versions:
+    parameters:
+      - $ref: "#/parameters/casa-version"
+      - $ref: "#/parameters/casa-capability"
+      - $ref: "#/parameters/casa-telescope"
+    get:
+      tags:
+        - "casa-matrix"
+      summary: "Get a list of valid CASA versions for processing"
+      description: "Get a list of valid CASA versions for processing, providing the optional parameters will filter the versions"
+      operationId: "get_casa_versions"
+      responses:
+        404:
+          description: "No CASA versions found"
+        200:
+          description: "successful operation"
+          schema:
+            $ref: "#/definitions/CasaVersions"
+  /casa_matrix/get_casa_recipe:
+    parameters:
+      - $ref: "#/parameters/casa-capability"
+    get:
+      tags:
+        - "casa-matrix"
+      summary: "Get a CASA recipe for processing the given capability"
+      description: "Get a valid CASA recipe for processing the given capability"
+      operationId: "get_casa_recipe"
+      responses:
+        404:
+          description: "No CASA recipe found"
+        200:
+          description: "successful operation"
+          schema:
+            type: "string"
+  /casa_matrix/add_casa_version:
+    parameters:
+      - $ref: "#/parameters/casa-version"
+      - $ref: "#/parameters/casa-capabilities"
+      - $ref: "#/parameters/casa-compatible"
+    post:
+      tags:
+        - "casa-matrix"
+      summary: "Add a CASA version to the matrix tables"
+      description: "Add a CASA version to the matrix tables to enable for the given capability list"
+      operationId: "add_casa_version"
+      responses:
+        404:
+          description: "CASA version not added"
+        200:
+          description: "successful operation"
+          schema:
+            type: "boolean"
+  /casa_matrix/update_casa_version:
+    parameters:
+      - $ref: "#/parameters/casa-version"
+      - $ref: "#/parameters/casa-capabilities"
+      - $ref: "#/parameters/casa-compatible"
+    post:
+      tags:
+        - "casa-matrix"
+      summary: "Update a CASA version in the matrix tables"
+      description: "Update a CASA version in the matrix tables to enable for the given capability list"
+      operationId: "update_casa_version"
+      responses:
+        404:
+          description: "CASA version not updated"
+        200:
+          description: "successful operation"
+          schema:
+            type: "boolean"
+  /casa_matrix/delete_casa_version:
+    parameters:
+      - $ref: "#/parameters/casa-version"
+    post:
+      tags:
+        - "casa-matrix"
+      summary: "Delete a CASA version from the matrix tables"
+      description: "Delete a CASA version from the matrix tables"
+      operationId: "delete_casa_version"
+      responses:
+        404:
+          description: "CASA version not deleted"
+        200:
+          description: "successful operation"
+          schema:
+            type: "boolean"
+  /casa_matrix/make_casa_links:
+    post:
+      tags:
+        - "casa-matrix"
+      summary: "Refresh the links of installed CASA versions"
+      description: "Refresh the links of installed CASA versions, existing links will be replaced for this environment"
+      operationId: "make_casa_links"
+      responses:
+        404:
+          description: "Links not refreshed"
+        200:
+          description: "successful operation"
+          schema:
+            $ref: "#/definitions/CasaVersions"
   /workflows:
     get:
       tags:
@@ -1301,6 +1419,17 @@ definitions:
         type: integer
       project_code:
         type: string
+  CasaVersion:
+    type: "object"
+    properties:
+      version:
+        type: "string"
+      path:
+        type: "string"
+  CasaVersions:
+    type: "array"
+    items:
+      $ref: "#/definitions/CasaVersion"
   WorkflowList:
     type: "array"
     items:
@@ -1374,6 +1503,38 @@ parameters:
     description: "ID of the request"
     type: "integer"
     required: true
+  casa-version:
+    name: "version"
+    in: query
+    description: "CASA version"
+    type: "string"
+    required: false
+  casa-capability:
+    name: "capability"
+    in: query
+    description: "Capability to filter CASA versions"
+    type: "string"
+    required: false
+  casa-capabilities:
+    name: "capabilities"
+    in: query
+    description: "Capability list"
+    type: "array"
+    items:
+      type: "string"
+    required: true
+  casa-telescope:
+    name: "telescope"
+    in: query
+    description: "Telescope to filter CASA versions"
+    type: "string"
+    required: false
+  casa-compatible:
+    name: "is_cluster_compatible"
+    in: query
+    description: "Flag to signal if version is cluster compatible"
+    type: boolean
+    required: false
 
 externalDocs:
   description: "More about the capability service"
diff --git a/services/capability/capability/routes.py b/services/capability/capability/routes.py
index 09c335060..ce72f5e5b 100644
--- a/services/capability/capability/routes.py
+++ b/services/capability/capability/routes.py
@@ -51,6 +51,7 @@ def includeme(config: Configurator):
     capability_request_routes(config)
     capability_version_routes(config)
     capability_execution_routes(config)
+    casa_matrix_routes(config)
 
 
 def default_routes(config: Configurator):
@@ -264,3 +265,22 @@ def capability_execution_routes(config: Configurator) -> None:
         pattern=f"{request_url}/create_version",
         request_method="POST",
     )
+
+
+def casa_matrix_routes(config: Configurator) -> None:
+    """
+    Server routes related to the CASA version matrix.
+
+    :param config: Pyramid server config object
+    """
+
+    # GET
+    config.add_route(name="get_casa_version", pattern=f"casa_matrix/get_casa_version", request_method="GET")
+    config.add_route(name="get_casa_versions", pattern=f"casa_matrix/get_casa_versions", request_method="GET")
+    config.add_route(name="get_casa_recipe", pattern=f"casa_matrix/get_casa_recipe", request_method="GET")
+
+    # POST
+    config.add_route(name="add_casa_version", pattern=f"casa_matrix/add_casa_version", request_method="POST")
+    config.add_route(name="update_casa_version", pattern=f"casa_matrix/update_casa_version", request_method="POST")
+    config.add_route(name="delete_casa_version", pattern=f"casa_matrix/delete_casa_version", request_method="POST")
+    config.add_route(name="make_casa_links", pattern=f"casa_matrix/make_casa_links", request_method="POST")
diff --git a/services/capability/capability/views/capability.py b/services/capability/capability/views/capability.py
index d0c52f182..bbdd703bb 100644
--- a/services/capability/capability/views/capability.py
+++ b/services/capability/capability/views/capability.py
@@ -25,7 +25,6 @@ concerning capabilities themselves
 import http
 
 from pycapo import CapoConfig
-
 from pyramid.httpexceptions import (
     HTTPBadRequest,
     HTTPExpectationFailed,
@@ -285,3 +284,132 @@ def get_analyst_email(request: Request) -> Response:
         return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{analyst_email}"})
     else:
         return HTTPNotFound(detail=f"No workspaces-analyst email found.")
+
+
+@view_config(route_name="get_casa_version", renderer="json")
+def get_casa_version(request: Request) -> Response:
+    """
+    Pyramid view that gets a CASA version for processing.
+
+    :param request: GET request
+    :return: Response containing the CASA version and path
+        or a 404 response (HTTPNotFound) if one isn't returned
+    """
+    casa_version = request.casa_matrix_service.get_version(
+        request.params["version"], request.params["capability"], request.params["telescope"]
+    )
+
+    if casa_version:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{casa_version}"})
+    else:
+        return HTTPNotFound(detail=f"No CASA version found.")
+
+
+@view_config(route_name="get_casa_versions", renderer="json")
+def get_casa_versions(request: Request) -> Response:
+    """
+    Pyramid view that gets a list of CASA versions for processing.
+
+    :param request: GET request
+    :return: Response containing a list of CASA versions and their paths
+        or a 404 response (HTTPNotFound) if none are returned
+    """
+    casa_versions = request.casa_matrix_service.get_versions(request.params["capability"])
+
+    if casa_versions:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{casa_versions}"})
+    else:
+        return HTTPNotFound(detail=f"No CASA versions found.")
+
+
+@view_config(route_name="get_casa_recipe", renderer="json")
+def get_casa_recipe(request: Request) -> Response:
+    """
+    Pyramid view that gets a CASA recipe for the given capability.
+
+    :param request: GET request
+    :return: Response containing the CASA recipe
+        or a 404 response (HTTPNotFound) if one isn't returned
+    """
+    casa_recipe = request.casa_matrix_service.get_recipe(request.params["capability"])
+
+    if casa_recipe:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{casa_recipe}"})
+    else:
+        return HTTPNotFound(detail=f"No CASA recipe found.")
+
+
+@view_config(route_name="add_casa_version", renderer="json")
+def add_casa_version(request: Request) -> Response:
+    """
+    Pyramid view that adds a CASA version to the matrix.
+
+    :param request: POST request
+    :return: Response containing true if the new matrix version was added
+        or a 404 response (HTTPNotFound) if one isn't added
+    """
+    added = request.casa_matrix_service.add_version(
+        request.params["version"],
+        request.params["capabilities"],
+        request.params["is_cluster_compatible"],
+    )
+
+    if added:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{added}"})
+    else:
+        return HTTPNotFound(detail=f"Matrix version not added")
+
+
+@view_config(route_name="update_casa_version", renderer="json")
+def update_casa_version(request: Request) -> Response:
+    """
+    Pyramid view that updates a CASA version in the matrix.
+
+    :param request: POST request
+    :return: Response containing true if the matrix version was updated
+        or a 404 response (HTTPNotFound) if one isn't updated
+    """
+    updated = request.casa_matrix_service.update_version(
+        request.params["version"],
+        request.params["capabilities"],
+        request.params["is_cluster_compatible"],
+    )
+
+    if updated:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{updated}"})
+    else:
+        return HTTPNotFound(detail=f"Matrix version not updated")
+
+
+@view_config(route_name="delete_casa_version", renderer="json")
+def delete_casa_version(request: Request) -> Response:
+    """
+    Pyramid view that deletes a CASA version from the matrix.
+
+    :param request: POST request
+    :return: Response containing true if version was deleted from the matrix
+        or a 404 response (HTTPNotFound) if one isn't deleted
+    """
+    deleted = request.casa_matrix_service.delete_version(request.params["version"])
+
+    if deleted:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{deleted}"})
+    else:
+        return HTTPNotFound(detail=f"Matrix version not deleted")
+
+
+@view_config(route_name="make_casa_links", renderer="json")
+def make_casa_links(request: Request) -> Response:
+    """
+    Pyramid view that refreshes the list of symlinks pointing to installed CASA versions.
+
+    :param request: POST request
+    :return: Response containing the list of installed versions that were linked
+        or a 404 response (HTTPNotFound) if no links were updated
+    """
+    found_versions = request.casa_matrix_service.make_links()
+
+    if found_versions:
+        return Response(status_int=http.HTTPStatus.OK, json_body={"resp": f"{found_versions}"})
+    else:
+        return HTTPNotFound(detail=f"CASA links not updated")
-- 
GitLab