Skip to content

Commit

Permalink
rolling back gunicorn approach, its just adding complexing for a mock…
Browse files Browse the repository at this point in the history
… service
  • Loading branch information
rabellino-noaa committed Jun 28, 2024
1 parent 74d4204 commit f51d6d9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 105 deletions.
25 changes: 3 additions & 22 deletions docker/mockims/dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,14 @@ LABEL maintainer ${maintainer}
WORKDIR /python/ims_service

# Copy source files
COPY ./python/idsse_testing/ims_service/src/ims_service.py /app/app.py
COPY ./python/ims_service/src/ims_service.py /python/ims_service/

# (TEMPORARY) Copy canned criteria files. To be removed when integration with IMS API exists
COPY ./python/idsse_testing/ims_service/profiles/*.json /python/profiles/
COPY ./python/ims_service/profiles/*.json /python/profiles/

# The volume mapping here is kind of strange for k8s deployment, because if we map an empty volume to /criteria
# then the temp copy of json above will get blown away by the volume mapping...just omit it for k8s deployment
# for now.
#VOLUME /python/profiles

# Run with flask (local only)
#ENTRYPOINT [ "python3", "/app/app.py" ]

# Run with gunicorn
ENV PORT 5000
ENV WORKERS 2
ENV LOGLEVEL info

EXPOSE $PORT

# Create entry script to run service
RUN echo "#!/bin/sh" > /app/entry.sh && \
echo "gunicorn --chdir /app -w \${WORKERS} \\" >> /app/entry.sh && \
echo " -b 0.0.0.0:\${PORT} --worker-tmp-dir /dev/shm \\" >> /app/entry.sh && \
echo " --enable-stdio-inheritance --access-logfile - --error-logfile - \\" >> /app/entry.sh && \
echo " --access-logformat '%(h)s %(t)s \"%(r)s\" %(s)s %(b)s \"%(f)s\" \"%(a)s\" %(T)s %(M)s' \\" >> /app/entry.sh && \
echo " --log-level \${LOGLEVEL} 'app:app' " >> /app/entry.sh && \
chmod a+x /app/entry.sh

ENTRYPOINT ["/app/entry.sh"]
ENTRYPOINT [ "python3", "/python/ims_service/ims_service.py" ]
106 changes: 23 additions & 83 deletions python/idsse_testing/ims_service/src/ims_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,91 +11,44 @@
# pylint: disable=missing-function-docstring,redefined-outer-name,protected-access
# pylint: disable=unused-argument, disable=duplicate-code
import json
import logging
import os

from glob import glob
from os import path

from flask import Flask, Response, request, jsonify
from flask_cors import CORS
from flask import Flask, request, jsonify

app = Flask(__name__)
app.config['GSL_KEY'] = 'GSL_234386fd-eb0a-408f-9ea2-149506a742bf'

# The joined profiles from the JSON examples...
ims_request = {'errors': [], 'profiles': []}

logger = logging.getLogger(__name__)

# URLs that webserver will tell browsers to allow requests from (CORS setting)
ALLOWED_ORIGINS = [
'http://localhost:5173',
'https://sites.gsl.noaa.gov'
]

class IMSService:
"""Handles HTTP access to mock IMS service"""

def profiles(self) -> Response:
print('----DEBUG----')
print('Received GET request for all events, with headers:', request.headers)
print(' request.args.keys are:', request.args.keys())
print('DEBUG: request.headers.get("X-Api-Key") =', request.headers.get("X-Api-Key"))
print('DEBUG: app.config["GSL_KEY"] =', app.config['GSL_KEY'])
print('DEBUG: request.args.get("dataSource") =', request.args.get('dataSource'))

# logger doesn't get printed in the deployed version for some reason
# since mock-ims is a temporary service, I'm not going to spend time debugging this
# and will just use print statements instead
#logger.info('Received GET request for all events, with headers: %s', request.headers)
#logger.info(' request.args.keys are: %s', request.args.keys())

# First check for the key argument and that it matches the expected value...
if request.headers.get("X-Api-Key") != app.config['GSL_KEY']:
return jsonify({"message": "ERROR: Unauthorized"}), 401

if len(request.args.keys()) != 1 or request.args.get('dataSource') != 'NBM':
# add one more check for ANY (currently IMS Gateway Request is using 'ANY')
if request.args.get('dataSource') != 'ANY':
return jsonify({"message": "Bad Request : Invalid argument!"}), 400
@app.route('/all_events', methods=['GET'])
def profiles():
# First check for the key argument and that it matches the expected value...
if request.headers.get("X-Api-Key") != app.config['GSL_KEY']:
return jsonify({"message": "ERROR: Unauthorized"}), 401

# Return the profiles...
return jsonify(ims_request)
if len(request.args.keys()) != 1 or request.args.get('dataSource') != 'NBM':
return jsonify({"message": "Bad Request : Invalid argument!"}), 400

def response(self) -> Response:
# First check for the key argument and that it matches the expected value...
if request.headers.get("X-Api-Key") != app.config['GSL_KEY']:
return jsonify({"message": "ERROR: Unauthorized"}), 401
# Return the profiles...
return jsonify(ims_request)

data = request.get_json() # Assumes the incoming data is in JSON format
print("Received POST request with data:", data)

# Process the data or perform any desired actions
return jsonify({"message": "POST request received successfully!"})
@app.route('/ims-response', methods=['POST'])
def response():
# First check for the key argument and that it matches the expected value...
if request.headers.get("X-Api-Key") != app.config['GSL_KEY']:
return jsonify({"message": "ERROR: Unauthorized"}), 401

class AppWrapper:
"""Web server class wrapping Flask app operations"""
# pylint: disable=too-few-public-methods
def __init__(self):
"""Build web app instance, mapping handler to endpoint"""
self.app: Flask = Flask(__name__)
# set CORS policy to allow specific origins on all endpoints
CORS(self.app, methods=['OPTIONS', 'GET', 'POST'], origins=ALLOWED_ORIGINS)
data = request.get_json() # Assumes the incoming data is in JSON format
print("Received POST request with data:", data)

self._service = IMSService()
# Process the data or perform any desired actions
return jsonify({"message": "POST request received successfully!"})

# register endpoints
self.app.add_url_rule('/all-events', methods=['GET'], view_func=self._service.profiles)
self.app.add_url_rule(
'/ims-response', methods=['POST'], view_func=self._service.response)

def run(self, **kwargs):
"""Start up web server"""
self.app.run(**kwargs)

def create_app() -> tuple[Flask, int]:
"""Entry point for the Flask web server to start"""
wrapper = AppWrapper()

return wrapper.app

if __name__ == '__main__':
# Load the canned profiles from the resources directory into a single dictionary to form
Expand All @@ -106,7 +59,6 @@ def create_app() -> tuple[Flask, int]:
for file in glob('*.json', root_dir=profile_dir)
]

print('Loading canned support profiles from:', json_files)
# json_files = sorted(glob('../profiles/*.json'))
for json_file in json_files:
with open(json_file, 'r', encoding="utf-8") as jf:
Expand All @@ -118,17 +70,5 @@ def create_app() -> tuple[Flask, int]:
ims_request['profiles'].append(pro)
# ims_request = ims_request | {os.path.basename(json_file).strip('.json') : profile}

print('Loaded profiles:', ims_request)

app = create_app()
# host=0.0.0.0 is required for flask to work properly in docker and k8s env
app.run(host='0.0.0.0', port=5000)

# set up container run time with gunicorn
elif 'gunicorn' in os.getenv('SERVER_SOFTWARE', default=''): # pragma: no cover
app = Flask(__name__)
app.config['GSL_KEY'] = '8209c979-e3de-402e-a1f5-556d650ab889'

print('TEST: Running from gunicorn main block')
print(app.config['GSL_KEY'])
print('----DEBUG----')
app.run(host='0.0.0.0', port=5000)

0 comments on commit f51d6d9

Please sign in to comment.