x-atlas-consortia / ubkg-api

A web service for the Unified Biomedical Knowlege Graph system
MIT License
0 stars 0 forks source link

Fix `/status` error from uWSGI docker deployment #114

Closed yuanzhou closed 4 months ago

yuanzhou commented 5 months ago

During the release deployment after merging PR https://github.com/x-atlas-consortia/ubkg-api/pull/112 I ran into an issue with the api docker and it failed to start. I had to manually hack into the code to get it up running.

[data-distillery@ip-172-31-30-102 ubkg_api]$ vi wsgi.py 

from app import UbkgAPI

application = UbkgAPI('app.cfg', '../../').app

if __name__ == '__main__':
    application.run()

But still getting this incorrect response from https://datadistillery.api.sennetconsortium.org/status

{"build":"unsupported operand type(s) for /: 'str' and 'str'","neo4j_connection":true,"version":"unsupported operand type(s) for /: 'str' and 'str'"}

I identified the cause of this deployment issue (I had fixed the typo prior to merging @AlanSimmons PR to resolve the conflict).

We will need to update the wsgi.py without using hardcoded path to fix the uWSGI docker deployment.

AlanSimmons commented 5 months ago

@yuanzhou When I run in my local setup (local neo4j, local ubkg-api, MacOS), I get the following:

{ "build": "[Errno 2] No such file or directory: '/Users/jas971/PycharmProjects/pythonProject/ubkg-api/BUILD'", "neo4j_connection": true, "version": "2.1.0" }

I assumed that the error was because there was no file named BUILD in the application root. I also assumed that the deployment would create a BUILD file. I get the same type of error whether I start from ubkg-api or from hs-ontology-api.

Comparing the error returned with the code behind the status endpoint, I think that the problem is the use of the '/' character as a file path concatenator. For some reason, this doesn't work when the API is deployed in the docker. Perhaps it's an OS issue.

In any case, the solution might be as simple as using os.path.join instead of the slash character in the read_text() call. We could try this in DEV.

{
"build": "unsupported operand type(s) for /: 'str' and 'str'",
"neo4j_connection": true,
"version": "unsupported operand type(s) for /: 'str' and 'str'"
}
@status_blueprint.route('', methods = ['GET'])
def get_status():

    try:
        file_version_content = (current_app.package_base_dir / 'VERSION').read_text().strip()
    except Exception as e:
        file_version_content = str(e)

    try:
        file_build_content = (current_app.package_base_dir / 'BUILD').read_text().strip()
    except Exception as e:
        file_build_content = str(e)
yuanzhou commented 4 months ago

@AlanSimmons thanks for taking a look. When running locally, you'll first need to run this script https://github.com/x-atlas-consortia/ubkg-api/blob/neo4jv5/generate-build-version.sh which generates the BUILD file.

The issue I discovered is particularly for the docker deployment with uWSGI. We'll need to fix the wsgi.py using a fixed package path. Let's wait until @ChuckKollar is back to take a look since he introduced this change https://github.com/x-atlas-consortia/ubkg-api/commit/a3a18f695baec4990473a5a6f29f6bed4f3cb133

ChuckKollar commented 4 months ago

Joe, The problem causing the Python Error: "unsupported operand type(s) for /: 'str' and 'str'","neo4j_connection":true,"version":"unsupported operand type(s) for /: 'str' and 'str'"} issue is because the initialization of the class UbkgAPI is expecting a Python Path object and not a Python String object.

So something like this is necessary (e.g., calling it with a Path not a string)....

    ubkg_app = UbkgAPI('./app.cfg', Path(__file__).absolute().parent.parent).app

This is because when UbkgAPI is called as a library from within some other micro-service, it does not know where the base path is (where the VERSION and BUILD files are kept).

Within status_controller.py you can see that.... @status_blueprint.route('', methods = ['GET']) def get_status():

try:
    file_version_content = (current_app.package_base_dir / 'VERSION').read_text().strip()
except Exception as e:
    file_version_content = str(e)

the division operator is overloaded to do the right thing with a Path (append). When you pass it a string the complaint is that you can't use the division operator on two strings.