Fix the /health endpoint (#1847)

* Fix the /health endpoint

 #1846

Keep both the old and new locations until the deployments are upgraded.
This commit is contained in:
bmccandless
2020-09-17 17:14:08 -07:00
committed by GitHub
parent 25c272ae8e
commit 14fbe0aa77
2 changed files with 44 additions and 8 deletions
+32 -6
View File
@@ -99,6 +99,10 @@ def dataset_index(url_dataroot=None, dataset=None):
) )
# TODO: This route will be deprecated, but needs to be left for a short time until all the
# deployments are upgraded to the new location for the health check (or else the upgrade will
# fail). Once the upgrade is complete, the deployments can move to the new health check URL
# and this route will be removed.
@webbp.route("/health", methods=["GET"]) @webbp.route("/health", methods=["GET"])
@cache_control_always(no_store=True) @cache_control_always(no_store=True)
def health(): def health():
@@ -224,6 +228,13 @@ def dataroot_index():
return redirect(config.server_config.multi_dataset__index) return redirect(config.server_config.multi_dataset__index)
class HealthAPI(Resource):
@cache_control(no_store=True)
def get(self):
config = current_app.app_config
return health_check(config)
class DatasetResource(Resource): class DatasetResource(Resource):
"""Base class for all Resources that act on datasets.""" """Base class for all Resources that act on datasets."""
@@ -312,8 +323,18 @@ class LayoutObsAPI(DatasetResource):
return common_rest.layout_obs_put(request, data_adaptor) return common_rest.layout_obs_put(request, data_adaptor)
def get_api_resources(bp_api, url_dataroot=None): def get_api_base_resources(bp_base):
api = Api(bp_api) """Add resources that are accessed from the api_base_url"""
api = Api(bp_base)
# Diagnostics routes
api.add_resource(HealthAPI, "/health")
return api
def get_api_dataroot_resources(bp_dataroot, url_dataroot=None):
"""Add resources that refer to a dataset"""
api = Api(bp_dataroot)
def add_resource(resource, url): def add_resource(resource, url):
"""convenience function to make the outer function less verbose""" """convenience function to make the outer function less verbose"""
@@ -385,18 +406,23 @@ class Server:
parse = urlparse(api_base_url) parse = urlparse(api_base_url)
api_path = parse.path api_path = parse.path
bp_base = Blueprint("bp_base", __name__, url_prefix=api_path)
base_resources = get_api_base_resources(bp_base)
self.app.register_blueprint(base_resources.blueprint)
if app_config.is_multi_dataset(): if app_config.is_multi_dataset():
# NOTE: These routes only allow the dataset to be in the directory # NOTE: These routes only allow the dataset to be in the directory
# of the dataroot, and not a subdirectory. We may want to change # of the dataroot, and not a subdirectory. We may want to change
# the route format at some point # the route format at some point
for dataroot_dict in server_config.multi_dataset__dataroot.values(): for dataroot_dict in server_config.multi_dataset__dataroot.values():
url_dataroot = dataroot_dict["base_url"] url_dataroot = dataroot_dict["base_url"]
bp_api = Blueprint( bp_dataroot = Blueprint(
f"api_dataset_{url_dataroot}", __name__, f"api_dataset_{url_dataroot}", __name__,
url_prefix=f"{api_path}/{url_dataroot}/<dataset>" + api_version url_prefix=f"{api_path}/{url_dataroot}/<dataset>" + api_version
) )
resources = get_api_resources(bp_api, url_dataroot) dataroot_resources = get_api_dataroot_resources(bp_dataroot, url_dataroot)
self.app.register_blueprint(resources.blueprint) self.app.register_blueprint(dataroot_resources.blueprint)
self.app.add_url_rule( self.app.add_url_rule(
f"/{url_dataroot}/<dataset>/", f"/{url_dataroot}/<dataset>/",
f"dataset_index_{url_dataroot}", f"dataset_index_{url_dataroot}",
@@ -412,7 +438,7 @@ class Server:
else: else:
bp_api = Blueprint("api", __name__, url_prefix=f"{api_path}{api_version}") bp_api = Blueprint("api", __name__, url_prefix=f"{api_path}{api_version}")
resources = get_api_resources(bp_api) resources = get_api_dataroot_resources(bp_api)
self.app.register_blueprint(resources.blueprint) self.app.register_blueprint(resources.blueprint)
self.app.add_url_rule( self.app.add_url_rule(
"/static/<path:filename>", "/static/<path:filename>",
+12 -2
View File
@@ -142,7 +142,7 @@ class AppConfigTest(unittest.TestCase):
config = AppConfig() config = AppConfig()
backend_port = find_available_port("localhost", 10000) backend_port = find_available_port("localhost", 10000)
config.update_server_config( config.update_server_config(
app__api_base_url=f"http://localhost:{backend_port}/additional/path/before/dataroot", app__api_base_url=f"http://localhost:{backend_port}/additional/path",
multi_dataset__dataroot=f"{PROJECT_ROOT}/example-dataset" multi_dataset__dataroot=f"{PROJECT_ROOT}/example-dataset"
) )
@@ -151,11 +151,21 @@ class AppConfigTest(unittest.TestCase):
with test_server(["-p", str(backend_port)], app_config=config) as server: with test_server(["-p", str(backend_port)], app_config=config) as server:
session = requests.Session() session = requests.Session()
self.assertEqual(server, f"http://localhost:{backend_port}") self.assertEqual(server, f"http://localhost:{backend_port}")
response = session.get(f"{server}/additional/path/before/dataroot/d/pbmc3k.h5ad/api/v0.2/config") response = session.get(f"{server}/additional/path/d/pbmc3k.h5ad/api/v0.2/config")
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
data_config = response.json() data_config = response.json()
self.assertEqual(data_config["config"]["displayNames"]["dataset"], "pbmc3k") self.assertEqual(data_config["config"]["displayNames"]["dataset"], "pbmc3k")
# test the health check at the correct url
response = session.get(f"{server}/additional/path/health")
assert response.json()["status"] == "pass"
# also check that the old URL still works.
# NOTE: this old URL location will soon be deprecated, and when that happens
# this check can be removed.
response = session.get(f"{server}/health")
assert response.json()["status"] == "pass"
def test_configfile_with_specialization(self): def test_configfile_with_specialization(self):
# test that per_dataset_config config load the default config, then the specialized config # test that per_dataset_config config load the default config, then the specialized config