This is an automated email from the ASF dual-hosted git repository.
jedcunningham pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 8cebfa7c82 Remove legacy dag details page and redirect to grid (#37232)
8cebfa7c82 is described below
commit 8cebfa7c82f5af3f9d12370602cf640a1d06daff
Author: Brent Bovenzi <[email protected]>
AuthorDate: Wed Feb 7 19:41:49 2024 -0500
Remove legacy dag details page and redirect to grid (#37232)
---
airflow/www/templates/airflow/dag_details.html | 144 -------------------------
airflow/www/views.py | 75 +------------
tests/www/views/test_views_acl.py | 13 ---
tests/www/views/test_views_tasks.py | 31 ------
4 files changed, 2 insertions(+), 261 deletions(-)
diff --git a/airflow/www/templates/airflow/dag_details.html
b/airflow/www/templates/airflow/dag_details.html
deleted file mode 100644
index e6b7152d7c..0000000000
--- a/airflow/www/templates/airflow/dag_details.html
+++ /dev/null
@@ -1,144 +0,0 @@
-{#
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-#}
-
-{% extends "airflow/dag.html" %}
-
-{% block page_title %}{{ dag.dag_id }} - DAG Details - {{ appbuilder.app_name
}}{% endblock %}
-
-{% block content %}
- {{ super() }}
- <h3>{{ title }}</h3>
- <div>
- {% for state, count in states %}
- <a
- class="btn"
- style="border: 0; background-color:{{ State.color(state)}}; color: {{
State.color_fg(state) }};"
- href="{{ url_for('TaskInstanceModelView.list',
_flt_3_dag_id=dag.dag_id, _flt_3_state=state) }}">
- {{ state }} <span class="badge">{{ count }}</span>
- </a>
- {% endfor %}
- </div>
- <br>
- <table class="table table-striped table-bordered">
- {% if dag.parent_dag is defined and dag.parent_dag %}
- <tr>
- <th>Parent DAG</th>
- <td>
- <a href="{{ url_for('Airflow.' + dag.default_view,
dag_id=dag.parent_dag.dag_id) }}">{{ dag.parent_dag.dag_id }}</a>
- </td>
- </tr>
- {% endif %}
- <tr>
- <th>Schedule Interval</th>
- <td>{{ dag.schedule_interval }}</td>
- </tr>
- <tr>
- <th>Catchup</th>
- <td>{{ dag.catchup }}</td>
- </tr>
- {% if dag.catchup %}
- <tr>
- <th>Start Date</th>
- <td><time datetime="{{ dag.start_date }}">{{ dag.start_date
}}</time></td>
- </tr>
- {% else %}
- <tr>
- <th>Started</th>
- <td>{{ states|length > 0 }}</td>
- </tr>
- {% endif %}
- <tr>
- <th>End Date</th>
- <td><time datetime="{{ dag.end_date }}">{{ dag.end_date }}</time></td>
- </tr>
- <tr>
- <th>Max Active Runs</th>
- <td>{{ active_runs | length }} / {{ dag.max_active_runs }}</td>
- </tr>
- <tr>
- <th>Max Active Tasks</th>
- <td>{{ dag.max_active_tasks }}</td>
- </tr>
- <tr>
- <th>Default Args</th>
- <td class="wrap">{{ dag.default_args | pprint }}</td>
- </tr>
- <tr>
- <th>Tasks Count</th>
- <td>{{ dag.tasks|length }}</td>
- </tr>
- <tr>
- <th>Task IDs</th>
- <td>{{ dag.task_ids }}</td>
- </tr>
- <tr>
- <th>Relative file location</th>
- <td>{{ dag.relative_fileloc }}</td>
- </tr>
- <tr>
- <th>Owner</th>
- <td>{{ dag.owner }}</td>
- </tr>
- <tr>
- <th>Owner Links</th>
- <td>
- {% if dag.owner_links %}
- {{ dag.owner_links }}
- {% else %}
- None
- {% endif %}
- </td>
- </tr>
- <tr>
- <th>DAG Run Timeout</th>
- <td>{{ dag.dagrun_timeout }}</td>
- </tr>
- <tr>
- <th>Tags</th>
- <td>
- {% if tags is defined and tags %}
- {% for tag in tags | sort(attribute='name') %}
- <a class="label label-info"
- href="{{ url_for('Airflow.index', tags=tag.name) }}"
- style="margin: 3px 6px 3px 0;"
- title="All DAGs tagged “{{ tag.name }}”"
- >
- {{ tag.name }}
- </a>
- {% endfor %}
- {% else %}
- None
- {% endif %}
- </td>
- </tr>
- </table>
- <h5>DagModel debug information</h5>
- <table class="table table-striped table-bordered">
- <tr>
- <th>Attribute</th>
- <th>Value</th>
- </tr>
- {% for attr, value in dag_model_attrs %}
- <tr>
- <td>{{ attr }}</td>
- <td class="code wrap">{{ value }}</td>
- </tr>
- {% endfor %}
- </table>
-{% endblock %}
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 0b7ede98dd..6e6caeba3c 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -1316,80 +1316,9 @@ class Airflow(AirflowBaseView):
return redirect(url_for("Airflow.dag_details",
**sanitize_args(request.args)))
@expose("/dags/<string:dag_id>/details")
- @auth.has_access_dag("GET", DagAccessEntity.RUN)
- @provide_session
- def dag_details(self, dag_id, session: Session = NEW_SESSION):
+ def dag_details(self, dag_id):
"""Get Dag details."""
- from airflow.models.dag import DagOwnerAttributes
-
- dag = get_airflow_app().dag_bag.get_dag(dag_id, session=session)
- dag_model = DagModel.get_dagmodel(dag_id, session=session)
- if not dag:
- flash(f'DAG "{dag_id}" seems to be missing.', "error")
- return redirect(url_for("Airflow.index"))
-
- wwwutils.check_import_errors(dag.fileloc, session)
- wwwutils.check_dag_warnings(dag.dag_id, session)
-
- title = "DAG Details"
- root = request.args.get("root", "")
-
- states = session.execute(
- select(TaskInstance.state, sqla.func.count(TaskInstance.dag_id))
- .where(TaskInstance.dag_id == dag_id)
- .group_by(TaskInstance.state)
- ).all()
-
- active_runs = models.DagRun.find(dag_id=dag_id,
state=DagRunState.RUNNING, external_trigger=False)
-
- tags =
session.scalars(select(models.DagTag).where(models.DagTag.dag_id ==
dag_id)).all()
-
- # TODO: convert this to a relationship
- owner_links =
session.execute(select(DagOwnerAttributes).filter_by(dag_id=dag_id)).all()
-
- attrs_to_avoid = [
- "schedule_datasets",
- "schedule_dataset_references",
- "task_outlet_dataset_references",
- "NUM_DAGS_PER_DAGRUN_QUERY",
- "serialized_dag",
- "tags",
- "default_view",
- "relative_fileloc",
- "dag_id",
- "description",
- "max_active_runs",
- "max_active_tasks",
- "schedule_interval",
- "owners",
- "dag_owner_links",
- "is_paused",
- ]
- attrs_to_avoid.extend(wwwutils.get_attr_renderer().keys())
- dag_model_attrs: list[tuple[str, Any]] = [
- (attr_name, attr)
- for attr_name, attr in (
- (attr_name, getattr(dag_model, attr_name))
- for attr_name in dir(dag_model)
- if not attr_name.startswith("_") and attr_name not in
attrs_to_avoid
- )
- if not callable(attr)
- ]
-
- return self.render_template(
- "airflow/dag_details.html",
- dag=dag,
- show_trigger_form_if_no_params=conf.getboolean("webserver",
"show_trigger_form_if_no_params"),
- dag_model=dag_model,
- title=title,
- root=root,
- states=states,
- State=State,
- active_runs=active_runs,
- tags=tags,
- owner_links=owner_links,
- dag_model_attrs=dag_model_attrs,
- )
+ return redirect(url_for("Airflow.grid", dag_id=dag_id))
@expose("/rendered-templates")
@auth.has_access_dag("GET", DagAccessEntity.TASK_INSTANCE)
diff --git a/tests/www/views/test_views_acl.py
b/tests/www/views/test_views_acl.py
index 83baf871e0..074483ed4a 100644
--- a/tests/www/views/test_views_acl.py
+++ b/tests/www/views/test_views_acl.py
@@ -459,19 +459,6 @@ def
test_code_success_for_all_dag_user(client_all_dags_codes, dag_id):
check_content_in_response(dag_id, resp)
-def test_dag_details_success(client_all_dags_dagruns):
- """User without RESOURCE_DAG_CODE can see the page, just not the ID."""
- url = "dag_details?dag_id=example_bash_operator"
- resp = client_all_dags_dagruns.get(url, follow_redirects=True)
- check_content_in_response("DAG Details", resp)
-
-
-def test_dag_details_failure(dag_faker_client):
- url = "dag_details?dag_id=example_bash_operator"
- resp = dag_faker_client.get(url, follow_redirects=True)
- check_content_not_in_response("DAG Details", resp)
-
-
@pytest.mark.parametrize(
"dag_id",
["example_bash_operator", "example_subdag_operator"],
diff --git a/tests/www/views/test_views_tasks.py
b/tests/www/views/test_views_tasks.py
index 1e64cfeeeb..00803a3575 100644
--- a/tests/www/views/test_views_tasks.py
+++ b/tests/www/views/test_views_tasks.py
@@ -178,21 +178,6 @@ def client_ti_without_dag_edit(app):
["Rendered Template"],
id="rendered-templates",
),
- pytest.param(
- "dag_details?dag_id=example_bash_operator",
- ["DAG Details"],
- id="dag-details-url-param",
- ),
- pytest.param(
- "dag_details?dag_id=example_subdag_operator.section-1",
- ["DAG Details"],
- id="dag-details-subdag-url-param",
- ),
- pytest.param(
- "dags/example_subdag_operator.section-1/details",
- ["DAG Details"],
- id="dag-details-subdag",
- ),
pytest.param(
"object/graph_data?dag_id=example_bash_operator",
["runme_1"],
@@ -450,22 +435,6 @@ def test_graph_view_without_dag_permission(app,
one_dag_perm_user_client):
check_content_in_response("Access is Denied", resp)
-def test_dag_details_trigger_origin_dag_details_view(app, admin_client):
- app.dag_bag.get_dag("test_graph_view").create_dagrun(
- run_type=DagRunType.SCHEDULED,
- execution_date=DEFAULT_DATE,
- data_interval=(DEFAULT_DATE, DEFAULT_DATE),
- start_date=timezone.utcnow(),
- state=State.RUNNING,
- )
-
- url = "/dags/test_graph_view/details"
- resp = admin_client.get(url, follow_redirects=True)
- params = {"origin": "/dags/test_graph_view/details"}
- href =
f"/dags/test_graph_view/trigger?{html.escape(urllib.parse.urlencode(params))}"
- check_content_in_response(href, resp)
-
-
def test_last_dagruns(admin_client):
resp = admin_client.post("last_dagruns", follow_redirects=True)
check_content_in_response("example_bash_operator", resp)