diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7258dad63..9318918864 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,6 +24,7 @@ Have questions about this document or anything not covered here? Come chat with * [Start a shell](#start-the-shell) * [Create a superuser](#create-a-superuser) * [Load the data](#load-the-data) + * [Building API Documentation](#build-documentation) * [Accessing the AWX web interface](#accessing-the-awx-web-interface) * [Purging containers and images](#purging-containers-and-images) * [What should I work on?](#what-should-i-work-on) @@ -261,6 +262,20 @@ You can optionally load some demo data. This will create a demo project, invento > This information will persist in the database running in the `tools_postgres_1` container, until the container is removed. You may periodically need to recreate this container, and thus the database, if the database schema changes in an upstream commit. +##### Building API Documentation + +AWX includes support for building [Swagger/OpenAPI +documentation](https://swagger.io). To build the documentation locally, run: + +```bash +(container)/awx_devel$ make swagger +``` + +This will write a file named `swagger.json` that contains the API specification +in OpenAPI format. A variety of online tools are available for translating +this data into more consumable formats (such as HTML). http://editor.swagger.io +is an example of one such service. + ### Accessing the AWX web interface You can now log into the AWX web interface at [https://localhost:8043](https://localhost:8043), and access the API directly at [https://localhost:8043/api/](https://localhost:8043/api/). diff --git a/awx/main/tests/docs/test_swagger_generation.py b/awx/main/tests/docs/test_swagger_generation.py index f4a04d02bd..1d6c507252 100644 --- a/awx/main/tests/docs/test_swagger_generation.py +++ b/awx/main/tests/docs/test_swagger_generation.py @@ -152,7 +152,10 @@ class TestSwaggerGeneration(): content_type, resp, request_data = value if method in node: status_code = str(status_code) - node[method].setdefault('produces', []).append(content_type) + if content_type: + produces = node[method].setdefault('produces', []) + if content_type not in produces: + produces.append(content_type) if request_data and status_code.startswith('2'): # DRF builds a schema based on the serializer # fields. This is _pretty good_, but if we @@ -181,5 +184,5 @@ class TestSwaggerGeneration(): def teardown_class(cls): with open('swagger.json', 'w') as f: f.write(force_bytes( - json.dumps(cls.JSON, cls=i18nEncoder, indent=5) + json.dumps(cls.JSON, cls=i18nEncoder) ))