Skip to content

Commit

Permalink
Move auxiliary spec from service app to openapi module
Browse files Browse the repository at this point in the history
  • Loading branch information
nadove-ucsc committed May 25, 2023
1 parent fda31ad commit 926933a
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 181 deletions.
197 changes: 25 additions & 172 deletions lambdas/service/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
AccessMethod,
)
from azul.health import (
Health,
HealthController,
)
from azul.indexer.document import (
Expand All @@ -75,6 +74,9 @@
responses,
schema,
)
from azul.openapi.spec import (
CommonEndpointSpecs,
)
from azul.plugins import (
ManifestFormat,
MetadataPlugin,
Expand Down Expand Up @@ -439,174 +441,49 @@ def oauth2_redirect():
body=oauth2_redirect_html)


@app.route('/openapi', methods=['GET'], cors=True, method_spec={
'summary': 'Return OpenAPI specifications for this service',
'description': 'This endpoint returns the [OpenAPI specifications]'
'(https://github.com/OAI/OpenAPI-Specification) for this '
'service. These are the specifications used to generate the '
'page you are visiting now.',
'responses': {
'200': {
'description': '200 response',
**responses.json_content(
schema.object(
openapi=str,
**{
k: schema.object()
for k in ('info', 'tags', 'servers', 'paths', 'components')
}
)
)
}
},
'tags': ['Auxiliary']
})
common_specs = CommonEndpointSpecs(app_name='service')


@app.route('/openapi', methods=['GET'], cors=True, **common_specs.openapi)
def openapi():
return Response(status_code=200,
headers={'content-type': 'application/json'},
body=app.spec())


health_up_key = {
'up': format_description('''
indicates the overall result of the health check
'''),
}

fast_health_keys = {
**{
prop.key: format_description(prop.description)
for prop in Health.fast_properties['service']
},
**health_up_key
}

health_all_keys = {
**{
prop.key: format_description(prop.description)
for prop in Health.all_properties
},
**health_up_key
}


def health_spec(health_keys: dict):
return {
'responses': {
f'{200 if up else 503}': {
'description': format_description(f'''
{'The' if up else 'At least one of the'} checked resources
{'are' if up else 'is not'} healthy.
The response consists of the following keys:
''') + ''.join(f'* `{k}` {v}' for k, v in health_keys.items()) + format_description(f'''
The top-level `up` key of the response is
`{'true' if up else 'false'}`.
''') + (format_description(f'''
{'All' if up else 'At least one'} of the nested `up` keys
{'are `true`' if up else 'is `false`'}.
''') if len(health_keys) > 1 else ''),
**responses.json_content(
schema.object(
additional_properties=schema.object(
additional_properties=True,
up=schema.enum(up)
),
up=schema.enum(up)
),
example={
k: up if k == 'up' else {} for k in health_keys
}
)
} for up in [True, False]
},
'tags': ['Auxiliary']
}


@app.route('/health', methods=['GET'], cors=True, method_spec={
'summary': 'Complete health check',
'description': format_description('''
Health check of the service and all resources it depends on. This may
take long time to complete and exerts considerable load on the service.
For that reason it should not be requested frequently or by automated
monitoring facilities that would be better served by the
[`/health/fast`](#operations-Auxiliary-get_health_fast) or
[`/health/cached`](#operations-Auxiliary-get_health_cached) endpoints.
'''),
**health_spec(health_all_keys)
})
@app.route('/health', methods=['GET'], cors=True, **common_specs.full_health)
def health():
return app.health_controller.health()


@app.route('/health/basic', methods=['GET'], cors=True, method_spec={
'summary': 'Basic health check',
'description': format_description('''
Health check of only the REST API itself, excluding other resources
the service depends on. A 200 response indicates that the service is
reachable via HTTP(S) but nothing more.
'''),
**health_spec(health_up_key)
})
@app.route('/health/basic',
methods=['GET'],
cors=True,
**common_specs.basic_health)
def basic_health():
return app.health_controller.basic_health()


@app.route('/health/cached', methods=['GET'], cors=True, method_spec={
'summary': 'Cached health check for continuous monitoring',
'description': format_description('''
Return a cached copy of the
[`/health/fast`](#operations-Auxiliary-get_health_fast) response.
This endpoint is optimized for continuously running, distributed health
monitors such as Route 53 health checks. The cache ensures that the
service is not overloaded by these types of health monitors. The cache
is updated every minute.
'''),
**health_spec(fast_health_keys)
})
@app.route('/health/cached',
methods=['GET'],
cors=True,
**common_specs.cached_health)
def cached_health():
return app.health_controller.cached_health()


@app.route('/health/fast', methods=['GET'], cors=True, method_spec={
'summary': 'Fast health check',
'description': format_description('''
Performance-optimized health check of the REST API and other critical
resources the service depends on. This endpoint can be requested more
frequently than [`/health`](#operations-Auxiliary-get_health) but
periodically scheduled, automated requests should be made to
[`/health/cached`](#operations-Auxiliary-get_health_cached).
'''),
**health_spec(fast_health_keys)
})
@app.route('/health/fast',
methods=['GET'],
cors=True,
**common_specs.fast_health)
def fast_health():
return app.health_controller.fast_health()


@app.route('/health/{keys}', methods=['GET'], cors=True, method_spec={
'summary': 'Selective health check',
'description': format_description('''
This endpoint allows clients to request a health check on a specific set
of resources. Each resource is identified by a *key*, the same key
under which the resource appears in a
[`/health`](#operations-Auxiliary-get_health) response.
'''),
**health_spec(health_all_keys)
}, path_spec={
'parameters': [
params.path(
'keys',
type_=schema.array(schema.enum(*sorted(Health.all_keys))),
description='''
A comma-separated list of keys selecting the health checks to be
performed. Each key corresponds to an entry in the response.
''')
],
})
@app.route('/health/{keys}',
methods=['GET'],
cors=True,
**common_specs.custom_health)
def custom_health(keys: Optional[str] = None):
return app.health_controller.custom_health(keys)

Expand All @@ -616,31 +493,7 @@ def update_health_cache(_event: chalice.app.CloudWatchEvent):
app.health_controller.update_cache()


@app.route('/version', methods=['GET'], cors=True, method_spec={
'summary': 'Describe current version of the Azul service',
'tags': ['Auxiliary'],
'responses': {
'200': {
'description': 'Version endpoint is reachable.',
**responses.json_content(
schema.object(
git=schema.object(
commit=str,
dirty=bool
),
changes=schema.array(
schema.object(
title=str,
issues=schema.array(str),
upgrade=schema.array(str),
notes=schema.optional(str)
)
)
)
)
}
}
})
@app.route('/version', methods=['GET'], cors=True, **common_specs.version)
def version():
from azul.changelog import (
compact_changes,
Expand Down
18 changes: 9 additions & 9 deletions lambdas/service/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"paths": {
"/openapi": {
"get": {
"summary": "Return OpenAPI specifications for this service",
"description": "This endpoint returns the [OpenAPI specifications](https://github.com/OAI/OpenAPI-Specification) for this service. These are the specifications used to generate the page you are visiting now.",
"summary": "Return OpenAPI specifications for this REST API",
"description": "\nThis endpoint returns the [OpenAPI specifications]'\n(https://github.com/OAI/OpenAPI-Specification) for this REST\nAPI. These are the specifications used to generate the page\nyou are visiting now.\n",
"responses": {
"200": {
"description": "200 response",
Expand Down Expand Up @@ -87,7 +87,7 @@
"/health": {
"get": {
"summary": "Complete health check",
"description": "\nHealth check of the service and all resources it depends on. This may\ntake long time to complete and exerts considerable load on the service.\nFor that reason it should not be requested frequently or by automated\nmonitoring facilities that would be better served by the\n[`/health/fast`](#operations-Auxiliary-get_health_fast) or\n[`/health/cached`](#operations-Auxiliary-get_health_cached) endpoints.\n",
"description": "\nHealth check of the service REST API and all\nresources it depends on. This may take long time to complete\nand exerts considerable load on the API. For that reason it\nshould not be requested frequently or by automated\nmonitoring facilities that would be better served by the\n[`/health/fast`](#operations-Auxiliary-get_health_fast) or\n[`/health/cached`](#operations-Auxiliary-get_health_cached)\nendpoints.\n",
"responses": {
"200": {
"description": "\nThe checked resources\nare healthy.\n\nThe response consists of the following keys:\n\n* `other_lambdas` \nIndicates whether the companion REST API responds to HTTP requests.\n* `queues` \nReturns information about the SQS queues used by the indexer.\n* `progress` \nThe number of Data Store bundles pending to be indexed and the number\nof index documents in need of updating.\n* `api_endpoints` \nIndicates whether important service API endpoints are operational.\n* `elasticsearch` \nIndicates whether the Elasticsearch cluster is responsive.\n* `up` \nindicates the overall result of the health check\n\n\nThe top-level `up` key of the response is\n`true`.\n\n\nAll of the nested `up` keys\nare `true`.\n",
Expand Down Expand Up @@ -186,7 +186,7 @@
"/health/basic": {
"get": {
"summary": "Basic health check",
"description": "\nHealth check of only the REST API itself, excluding other resources\nthe service depends on. A 200 response indicates that the service is\nreachable via HTTP(S) but nothing more.\n",
"description": "\nHealth check of only the REST API itself, excluding other\nresources that it depends on. A 200 response indicates that\nthe service is reachable via HTTP(S) but nothing\nmore.\n",
"responses": {
"200": {
"description": "\nThe checked resources\nare healthy.\n\nThe response consists of the following keys:\n\n* `up` \nindicates the overall result of the health check\n\n\nThe top-level `up` key of the response is\n`true`.\n\n",
Expand Down Expand Up @@ -275,7 +275,7 @@
"/health/cached": {
"get": {
"summary": "Cached health check for continuous monitoring",
"description": "\nReturn a cached copy of the\n[`/health/fast`](#operations-Auxiliary-get_health_fast) response.\nThis endpoint is optimized for continuously running, distributed health\nmonitors such as Route 53 health checks. The cache ensures that the\nservice is not overloaded by these types of health monitors. The cache\nis updated every minute.\n",
"description": "\nReturn a cached copy of the\n[`/health/fast`](#operations-Auxiliary-get_health_fast)\nresponse. This endpoint is optimized for continuously\nrunning, distributed health monitors such as Route 53 health\nchecks. The cache ensures that the service is not\noverloaded by these types of health monitors. The cache is\nupdated every minute.\n",
"responses": {
"200": {
"description": "\nThe checked resources\nare healthy.\n\nThe response consists of the following keys:\n\n* `elasticsearch` \nIndicates whether the Elasticsearch cluster is responsive.\n* `api_endpoints` \nIndicates whether important service API endpoints are operational.\n* `up` \nindicates the overall result of the health check\n\n\nThe top-level `up` key of the response is\n`true`.\n\n\nAll of the nested `up` keys\nare `true`.\n",
Expand Down Expand Up @@ -368,7 +368,7 @@
"/health/fast": {
"get": {
"summary": "Fast health check",
"description": "\nPerformance-optimized health check of the REST API and other critical\nresources the service depends on. This endpoint can be requested more\nfrequently than [`/health`](#operations-Auxiliary-get_health) but\nperiodically scheduled, automated requests should be made to\n[`/health/cached`](#operations-Auxiliary-get_health_cached).\n",
"description": "\nPerformance-optimized health check of the REST API and other\ncritical resources tht it depends on. This endpoint can be\nrequested more frequently than\n[`/health`](#operations-Auxiliary-get_health) but\nperiodically scheduled, automated requests should be made to\n[`/health/cached`](#operations-Auxiliary-get_health_cached).\n",
"responses": {
"200": {
"description": "\nThe checked resources\nare healthy.\n\nThe response consists of the following keys:\n\n* `elasticsearch` \nIndicates whether the Elasticsearch cluster is responsive.\n* `api_endpoints` \nIndicates whether important service API endpoints are operational.\n* `up` \nindicates the overall result of the health check\n\n\nThe top-level `up` key of the response is\n`true`.\n\n\nAll of the nested `up` keys\nare `true`.\n",
Expand Down Expand Up @@ -477,12 +477,12 @@
]
}
},
"description": "\nA comma-separated list of keys selecting the health checks to be\nperformed. Each key corresponds to an entry in the response.\n"
"description": "\nA comma-separated list of keys selecting the health\nchecks to be performed. Each key corresponds to an\nentry in the response.\n"
}
],
"get": {
"summary": "Selective health check",
"description": "\nThis endpoint allows clients to request a health check on a specific set\nof resources. Each resource is identified by a *key*, the same key\nunder which the resource appears in a\n[`/health`](#operations-Auxiliary-get_health) response.\n",
"description": "\nThis endpoint allows clients to request a health check on a\nspecific set of resources. Each resource is identified by a\n*key*, the same key under which the resource appears in a\n[`/health`](#operations-Auxiliary-get_health) response.\n",
"responses": {
"200": {
"description": "\nThe checked resources\nare healthy.\n\nThe response consists of the following keys:\n\n* `other_lambdas` \nIndicates whether the companion REST API responds to HTTP requests.\n* `queues` \nReturns information about the SQS queues used by the indexer.\n* `progress` \nThe number of Data Store bundles pending to be indexed and the number\nof index documents in need of updating.\n* `api_endpoints` \nIndicates whether important service API endpoints are operational.\n* `elasticsearch` \nIndicates whether the Elasticsearch cluster is responsive.\n* `up` \nindicates the overall result of the health check\n\n\nThe top-level `up` key of the response is\n`true`.\n\n\nAll of the nested `up` keys\nare `true`.\n",
Expand Down Expand Up @@ -580,7 +580,7 @@
},
"/version": {
"get": {
"summary": "Describe current version of the Azul service",
"summary": "Describe current version of this REST API",
"tags": [
"Auxiliary"
],
Expand Down
Loading

0 comments on commit 926933a

Please sign in to comment.