Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions cosmos/plugin/airflow2.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,16 @@ def dbt_docs(self) -> str:

@expose("/dbt_docs_index.html") # type: ignore[untyped-decorator]
@has_access(MENU_ACCESS_PERMISSIONS) # type: ignore[untyped-decorator]
def dbt_docs_index(self) -> tuple[str, int, dict[str, Any]]:
def dbt_docs_index(self) -> Any:
# The response is rendered inside the dbt_docs.html iframe, so a 404 here is also iframed.
# We serve a Cosmos-owned template whose "Return to the main page" link uses target="_top"
# to break out of the iframe (Airflow's default 404 link does not).
if dbt_docs_dir is None:
abort(404)
return self.render_template("dbt_docs_iframe_404.html"), 404 # type: ignore[no-untyped-call]
try:
html = open_file(op.join(dbt_docs_dir, dbt_docs_index_file_name), conn_id=dbt_docs_conn_id)
except FileNotFoundError:
abort(404)
return self.render_template("dbt_docs_iframe_404.html"), 404 # type: ignore[no-untyped-call]
else:
html = html.replace("</head>", f"{IFRAME_SCRIPT}</head>")
return html, 200, {"Content-Security-Policy": "frame-ancestors 'self'"}
Expand Down
15 changes: 15 additions & 0 deletions cosmos/plugin/templates/dbt_docs_iframe_404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Airflow 404</title>
<link rel="icon" type="image/png" href="{{ url_for('static', filename='pin_32.png') }}">
</head>
<body>
<div style="font-family: verdana; text-align: center; margin-top: 200px;">
<img src="{{ url_for('static', filename='pin_100.png') }}" width="50px" alt="pin-logo" />
<h1>Airflow 404</h1>
<p>Cosmos could not load the dbt docs index from the configured location.</p>
<a href="{{ url_for('Airflow.index') }}" target="_top">Return to the main page</a>
</div>
</body>
</html>
16 changes: 16 additions & 0 deletions tests/plugin/test_plugin_af2.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ def test_dbt_docs_artifact_missing(app, artifact):
assert response.status_code == 404


@pytest.mark.integration
@patch.object(cosmos.plugin.airflow2, "open_file")
def test_dbt_docs_index_404_breaks_out_of_iframe(mock_open_file, monkeypatch, app):
# Regression test for https://github.com/astronomer/astronomer-cosmos/issues/1828:
# the dbt_docs_index 404 is rendered inside the dbt_docs iframe, so its
# "Return to the main page" link must use target="_top" to break out.
monkeypatch.setattr("cosmos.plugin.airflow2.dbt_docs_dir", "path/to/docs/dir")
mock_open_file.side_effect = FileNotFoundError

response = app.get("/cosmos/dbt_docs_index.html")

assert response.status_code == 404
assert 'target="_top"' in response.text
assert "Return to the main page" in response.text


@pytest.mark.parametrize(
"path,open_file_callback",
[
Expand Down
Loading