diff --git a/greenwave/api_v1.py b/greenwave/api_v1.py index cd0a87b..1024d05 100644 --- a/greenwave/api_v1.py +++ b/greenwave/api_v1.py @@ -21,6 +21,54 @@ log = logging.getLogger(__name__) +@api.route('/', methods=['GET']) +def landing_page(): + """ + Landing page with links to documentation and other APIs and interpretation + of outcomes from ResultDB results (passed, error and incomplete). + + **Sample response**: + + .. sourcecode:: none + + HTTP/1.1 200 OK + Connection: close + Content-Length: 452 + Content-Type: application/json + Date: Tue, 05 Dec 2023 07:45:39 GMT + Server: Werkzeug/3.0.1 Python/3.12.0 + + { + "api_v1": "http://greenwave.example.com/api/v1.0", + "documentation": "https://gating-greenwave.readthedocs.io", + "koji_api": "https://koji.example.com/kojihub", + "outcomes_error": ["ERROR"], + "outcomes_incomplete": ["QUEUED", "RUNNING"], + "outcomes_passed": ["PASSED", "INFO"], + "remote_rule_policies": { + "*": "https://git.example.com/{pkg_namespace}{pkg_name}/raw/{rev}/gating.yaml", + "brew-build-group": "https://git.example.com/side-tags/{pkg_namespace}{pkg_name}.yaml" + }, + "resultsdb_api": "https://resultsdb.example.com/api/v2.0", + "waiverdb_api": "http://waiverdb.example.com/api/v1.0" + } + """ # noqa: E501 + return ( + jsonify({ + "documentation": current_app.config["DOCUMENTATION_URL"], + "api_v1": current_app.config["GREENWAVE_API_URL"], + "resultsdb_api": current_app.config["RESULTSDB_API_URL"], + "waiverdb_api": current_app.config["WAIVERDB_API_URL"], + "koji_api": current_app.config["KOJI_BASE_URL"], + "outcomes_passed": current_app.config["OUTCOMES_PASSED"], + "outcomes_error": current_app.config["OUTCOMES_ERROR"], + "outcomes_incomplete": current_app.config["OUTCOMES_INCOMPLETE"], + "remote_rule_policies": current_app.config["REMOTE_RULE_POLICIES"], + }), + 200, + ) + + @api.route('/version', methods=['GET']) def version(): """ diff --git a/greenwave/app_factory.py b/greenwave/app_factory.py index 505b507..db5f667 100644 --- a/greenwave/app_factory.py +++ b/greenwave/app_factory.py @@ -4,7 +4,7 @@ import logging.config from flask import Flask -from greenwave.api_v1 import api +from greenwave.api_v1 import api, landing_page from greenwave.utils import json_error, load_config, mangle_key from greenwave.policies import load_policies from greenwave.subjects.subject_type import load_subject_types @@ -50,6 +50,7 @@ def create_app(config_obj=None): # register blueprints app.register_blueprint(api, url_prefix="/api/v1.0") + app.add_url_rule('/', view_func=landing_page) app.add_url_rule('/healthcheck', view_func=healthcheck) # Initialize the cache. diff --git a/greenwave/config.py b/greenwave/config.py index 906593b..bbedd2e 100644 --- a/greenwave/config.py +++ b/greenwave/config.py @@ -94,6 +94,8 @@ class Config(object): SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "Lax" + DOCUMENTATION_URL = "https://gating-greenwave.readthedocs.io" + class ProductionConfig(Config): DEBUG = False diff --git a/greenwave/tests/test_landing_page.py b/greenwave/tests/test_landing_page.py new file mode 100644 index 0000000..1359a16 --- /dev/null +++ b/greenwave/tests/test_landing_page.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0+ +from pytest import mark + + +@mark.parametrize("endpoint", ("/", "/api/v1.0/")) +def test_landing_page(client, endpoint): + response = client.get(endpoint) + assert response.status_code == 200, response.text + data = response.json + config = client.application.config + assert data == { + "documentation": config["DOCUMENTATION_URL"], + "api_v1": config["GREENWAVE_API_URL"], + "resultsdb_api": config["RESULTSDB_API_URL"], + "waiverdb_api": config["WAIVERDB_API_URL"], + "koji_api": config["KOJI_BASE_URL"], + "outcomes_passed": list(config["OUTCOMES_PASSED"]), + "outcomes_error": list(config["OUTCOMES_ERROR"]), + "outcomes_incomplete": list(config["OUTCOMES_INCOMPLETE"]), + "remote_rule_policies": config["REMOTE_RULE_POLICIES"], + }