You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ka...@apache.org on 2020/06/29 20:43:36 UTC

[airflow] 04/04: Allow changing Task States Colors (#9520)

This is an automated email from the ASF dual-hosted git repository.

kaxilnaik pushed a commit to branch v1-10-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit f63b2496ccd0c78e3e918f59f473012c834967f1
Author: Kaxil Naik <ka...@gmail.com>
AuthorDate: Mon Jun 29 16:11:24 2020 +0100

    Allow changing Task States Colors (#9520)
    
    (cherry picked from commit e1108d42d2b3b9c049ed8872176923621b4c8d79)
---
 airflow/settings.py                            | 14 +++++++++++++
 airflow/utils/state.py                         |  3 +++
 airflow/www/app.py                             |  5 +++--
 airflow/www/templates/admin/master.html        |  7 +++++++
 airflow/www/templates/airflow/gantt.html       |  7 +++++++
 airflow/www/templates/airflow/graph.html       | 18 +++++++++--------
 airflow/www/templates/airflow/tree.html        | 27 +++++++++++---------------
 airflow/www/views.py                           |  3 ++-
 airflow/www_rbac/app.py                        |  4 +++-
 airflow/www_rbac/templates/airflow/gantt.html  |  7 +++++++
 airflow/www_rbac/templates/airflow/graph.html  | 18 +++++++++--------
 airflow/www_rbac/templates/airflow/master.html |  8 +++++++-
 airflow/www_rbac/templates/airflow/tree.html   | 27 +++++++++++---------------
 airflow/www_rbac/views.py                      |  3 ++-
 14 files changed, 97 insertions(+), 54 deletions(-)

diff --git a/airflow/settings.py b/airflow/settings.py
index c86d4b2..c56c3a8 100644
--- a/airflow/settings.py
+++ b/airflow/settings.py
@@ -153,6 +153,20 @@ Session = None
 # The JSON library to use for DAG Serialization and De-Serialization
 json = json
 
+# Dictionary containing State and colors associated to each state to
+# display on the Webserver
+STATE_COLORS = {
+    "queued": "gray",
+    "running": "lime",
+    "success": "green",
+    "failed": "red",
+    "up_for_retry": "gold",
+    "up_for_reschedule": "turquoise",
+    "upstream_failed": "orange",
+    "skipped": "pink",
+    "scheduled": "tan",
+}
+
 
 def policy(task_instance):
     """
diff --git a/airflow/utils/state.py b/airflow/utils/state.py
index 320b996..bb3ad39 100644
--- a/airflow/utils/state.py
+++ b/airflow/utils/state.py
@@ -21,6 +21,8 @@ from __future__ import unicode_literals
 
 from builtins import object
 
+from airflow.settings import STATE_COLORS
+
 
 class State(object):
     """
@@ -80,6 +82,7 @@ class State(object):
         SCHEDULED: 'tan',
         NONE: 'lightblue',
     }
+    state_color.update(STATE_COLORS)  # type: ignore
 
     @classmethod
     def color(cls, state):
diff --git a/airflow/www/app.py b/airflow/www/app.py
index c5c6066..30b9f75 100644
--- a/airflow/www/app.py
+++ b/airflow/www/app.py
@@ -32,7 +32,7 @@ import airflow
 from airflow import models, version, LoggingMixin
 from airflow.configuration import conf
 from airflow.models.connection import Connection
-from airflow.settings import Session
+from airflow.settings import Session, STATE_COLORS
 
 from airflow.www.blueprints import routes
 from airflow.logging_config import configure_logging
@@ -188,7 +188,8 @@ def create_app(config=None, testing=False):
                 'log_auto_tailing_offset': conf.getint(
                     'webserver', 'log_auto_tailing_offset', fallback=30),
                 'log_animation_speed': conf.getint(
-                    'webserver', 'log_animation_speed', fallback=1000)
+                    'webserver', 'log_animation_speed', fallback=1000),
+                'state_color_mapping': STATE_COLORS
             }
 
         @app.before_request
diff --git a/airflow/www/templates/admin/master.html b/airflow/www/templates/admin/master.html
index 531fac0..4300972 100644
--- a/airflow/www/templates/admin/master.html
+++ b/airflow/www/templates/admin/master.html
@@ -23,6 +23,13 @@
   <link href="{{ url_for('static', filename='bootstrap-theme.css') }}" rel="stylesheet">
   <link rel="icon" type="image/png" href="{{ url_for("static", filename="pin_32.png") }}">
   <link rel="stylesheet" type="text/css" href="{{ url_for("static", filename="main.css") }}">
+    <style type="text/css">
+    {% for state, state_color in state_color_mapping.items() %}
+      span.{{state}} {
+        background-color: {{state_color}};
+      }
+    {% endfor %}
+  </style>
 {% endblock %}
 
 {% block tail_js %}
diff --git a/airflow/www/templates/airflow/gantt.html b/airflow/www/templates/airflow/gantt.html
index f2bea89..1889853 100644
--- a/airflow/www/templates/airflow/gantt.html
+++ b/airflow/www/templates/airflow/gantt.html
@@ -24,6 +24,13 @@
 <link href="{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker-bs2.css') }}" rel="stylesheet"/>
 <link type="text/css" href="{{ url_for('static', filename='gantt.css') }}" rel="stylesheet" />
 <link type="text/css" href="{{ url_for('static', filename='tree.css') }}" rel="stylesheet" />
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    rect.{{state}} {
+      fill: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block body %}
diff --git a/airflow/www/templates/airflow/graph.html b/airflow/www/templates/airflow/graph.html
index dcbe4f9..880c463 100644
--- a/airflow/www/templates/airflow/graph.html
+++ b/airflow/www/templates/airflow/graph.html
@@ -27,6 +27,13 @@
 {{ super() }}
 <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='dagre.css') }}">
 <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='graph.css') }}">
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    g.node.{{state}} rect {
+      stroke: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block body %}
@@ -64,14 +71,9 @@
 
   <div>
     <div class="legend_item state" style="border-color:white;">no_status</div>
-    <div class="legend_item state" style="border-color:grey;">queued</div>
-    <div class="legend_item state" style="border-color:gold;">up_for_retry</div>
-    <div class="legend_item state" style="border-color:turquoise;">up_for_reschedule</div>
-    <div class="legend_item state" style="border-color:orange;">upstream_failed</div>
-    <div class="legend_item state" style="border-color:pink;">skipped</div>
-    <div class="legend_item state" style="border-color:red;">failed</div>
-    <div class="legend_item state" style="border-color:lime;">running</div>
-    <div class="legend_item state" style="border-color:green;">success</div>
+    {% for state, state_color in state_color_mapping.items() %}
+      <div class="legend_item state" style="border-color:{{state_color}};">{{state}}</div>
+    {% endfor %}
   </div>
   <div style="clear:both;"></div>
 </div>
diff --git a/airflow/www/templates/airflow/tree.html b/airflow/www/templates/airflow/tree.html
index 66255f6..cb43ae9 100644
--- a/airflow/www/templates/airflow/tree.html
+++ b/airflow/www/templates/airflow/tree.html
@@ -24,6 +24,13 @@
 {{ super() }}
 <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='tree.css') }}">
 <link href="{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker-bs2.css') }}" rel="stylesheet">
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    rect.{{state}} {
+      fill: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block body %}
@@ -46,22 +53,10 @@
 <div>
   <div class="legend_item" style="border: none;">no_status</div>
   <div class="square" style="background: white;"></div>
-  <div class="legend_item" style="border: none;">queued</div>
-  <div class="square" style="background: grey;"></div>
-  <div class="legend_item" style="border: none;">up_for_retry</div>
-  <div class="square" style="background: gold;"></div>
-  <div class="legend_item" style="border: none;">up_for_reschedule</div>
-  <div class="square" style="background: turquoise;"></div>
-  <div class="legend_item" style="border: none;">upstream_failed</div>
-  <div class="square" style="background: orange;"></div>
-  <div class="legend_item" style="border: none;">skipped</div>
-  <div class="square" style="background: pink;"></div>
-  <div class="legend_item" style="border: none;">failed</div>
-  <div class="square" style="background: red;"></div>
-  <div class="legend_item" style="border: none;">running</div>
-  <div class="square" style="background: lime;"></div>
-  <div class="legend_item" style="border: none;">success</div>
-  <div class="square" style="background: green;"></div>
+  {% for state, state_color in state_color_mapping.items() %}
+    <div class="legend_item" style="border: none;">{{state}}</div>
+    <div class="square" style="background: {{state_color}};"></div>
+  {% endfor %}
   {% for op in operators %}
   <div class="legend_circle" style="background:{{ op.ui_color }};">
   </div>
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 737b1e4..5a76d8b 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -75,7 +75,7 @@ from airflow.api.common.experimental.mark_tasks import (set_dag_run_state_to_run
 from airflow.exceptions import AirflowException
 from airflow.models import BaseOperator, Connection, DagRun, errors, XCom
 from airflow.models.dagcode import DagCode
-from airflow.settings import STORE_SERIALIZED_DAGS
+from airflow.settings import STATE_COLORS, STORE_SERIALIZED_DAGS
 from airflow.operators.subdag_operator import SubDagOperator
 from airflow.ti_deps.dep_context import RUNNING_DEPS, SCHEDULER_QUEUED_DEPS, DepContext
 from airflow.utils import timezone
@@ -2319,6 +2319,7 @@ class HomeView(AirflowViewMixin, AdminIndexView):
 
         state_color_mapping = State.state_color.copy()
         state_color_mapping["null"] = state_color_mapping.pop(None)
+        state_color_mapping.update(STATE_COLORS)
 
         return self.render(
             'airflow/dags.html',
diff --git a/airflow/www_rbac/app.py b/airflow/www_rbac/app.py
index ca6c4c8..8d59c85 100644
--- a/airflow/www_rbac/app.py
+++ b/airflow/www_rbac/app.py
@@ -35,6 +35,7 @@ from werkzeug.middleware.dispatcher import DispatcherMiddleware
 from airflow import settings, version
 from airflow.configuration import conf
 from airflow.logging_config import configure_logging
+from airflow.settings import STATE_COLORS
 from airflow.www_rbac.static_config import configure_manifest_files
 
 app = None  # type: Any
@@ -242,7 +243,8 @@ def create_app(config=None, session=None, testing=False, app_name="Airflow"):
                 'log_auto_tailing_offset': conf.getint(
                     'webserver', 'log_auto_tailing_offset', fallback=30),
                 'log_animation_speed': conf.getint(
-                    'webserver', 'log_animation_speed', fallback=1000)
+                    'webserver', 'log_animation_speed', fallback=1000),
+                'state_color_mapping': STATE_COLORS
             }
 
             if 'analytics_tool' in conf.getsection('webserver'):
diff --git a/airflow/www_rbac/templates/airflow/gantt.html b/airflow/www_rbac/templates/airflow/gantt.html
index 7a5e954..c5c4c42 100644
--- a/airflow/www_rbac/templates/airflow/gantt.html
+++ b/airflow/www_rbac/templates/airflow/gantt.html
@@ -21,6 +21,13 @@
 {{ super() }}
 <link type="text/css" href="{{ url_for('static', filename='css/gantt.css') }}" rel="stylesheet" />
 <link type="text/css" href="{{ url_for('static', filename='css/tree.css') }}" rel="stylesheet" />
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    rect.{{state}} {
+      fill: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block content %}
diff --git a/airflow/www_rbac/templates/airflow/graph.html b/airflow/www_rbac/templates/airflow/graph.html
index e2ab0f1..5fe326e 100644
--- a/airflow/www_rbac/templates/airflow/graph.html
+++ b/airflow/www_rbac/templates/airflow/graph.html
@@ -22,6 +22,13 @@
 {% block head_css %}
 {{ super() }}
 <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/graph.css') }}">
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    g.node.{{state}} rect {
+      stroke: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block content %}
@@ -58,14 +65,9 @@
 
   <div>
     <div class="legend_item state" style="border-color:white;">no_status</div>
-    <div class="legend_item state" style="border-color:grey;">queued</div>
-    <div class="legend_item state" style="border-color:gold;">up_for_retry</div>
-    <div class="legend_item state" style="border-color:turquoise;">up_for_reschedule</div>
-    <div class="legend_item state" style="border-color:orange;">upstream_failed</div>
-    <div class="legend_item state" style="border-color:pink;">skipped</div>
-    <div class="legend_item state" style="border-color:red;">failed</div>
-    <div class="legend_item state" style="border-color:lime;">running</div>
-    <div class="legend_item state" style="border-color:green;">success</div>
+  {% for state, state_color in state_color_mapping.items() %}
+    <div class="legend_item state" style="border-color:{{state_color}};">{{state}}</div>
+  {% endfor %}
   </div>
   <div style="clear:both;"></div>
 </div>
diff --git a/airflow/www_rbac/templates/airflow/master.html b/airflow/www_rbac/templates/airflow/master.html
index eb30303..fb2d382 100644
--- a/airflow/www_rbac/templates/airflow/master.html
+++ b/airflow/www_rbac/templates/airflow/master.html
@@ -27,7 +27,13 @@
   {% endif %}
   <link href="{{ url_for_asset('main.css') }}" rel="stylesheet">
   <link href="{{ url_for_asset('bootstrap-datetimepicker.min.css') }}" rel="stylesheet">
-
+  <style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    span.{{state}} {
+      background-color: {{state_color}};
+    }
+  {% endfor %}
+  </style>
   <link rel="icon" type="image/png" href="{{ url_for('static', filename='pin_32.png') }}">
 {% endblock %}
 
diff --git a/airflow/www_rbac/templates/airflow/tree.html b/airflow/www_rbac/templates/airflow/tree.html
index b8d167c..9d05a53 100644
--- a/airflow/www_rbac/templates/airflow/tree.html
+++ b/airflow/www_rbac/templates/airflow/tree.html
@@ -21,6 +21,13 @@
 {% block head_css %}
 {{ super() }}
 <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/tree.css') }}">
+<style type="text/css">
+  {% for state, state_color in state_color_mapping.items() %}
+    rect.{{state}} {
+      fill: {{state_color}};
+    }
+  {% endfor %}
+</style>
 {% endblock %}
 
 {% block content %}
@@ -44,22 +51,10 @@
 <div>
   <div class="legend_item" style="border: none;">no_status</div>
   <div class="square" style="background: white;"></div>
-  <div class="legend_item" style="border: none;">queued</div>
-  <div class="square" style="background: grey;"></div>
-  <div class="legend_item" style="border: none;">up_for_retry</div>
-  <div class="square" style="background: gold;"></div>
-  <div class="legend_item" style="border: none;">up_for_reschedule</div>
-  <div class="square" style="background: turquoise;"></div>
-  <div class="legend_item" style="border: none;">upstream_failed</div>
-  <div class="square" style="background: orange;"></div>
-  <div class="legend_item" style="border: none;">skipped</div>
-  <div class="square" style="background: pink;"></div>
-  <div class="legend_item" style="border: none;">failed</div>
-  <div class="square" style="background: red;"></div>
-  <div class="legend_item" style="border: none;">running</div>
-  <div class="square" style="background: lime;"></div>
-  <div class="legend_item" style="border: none;">success</div>
-  <div class="square" style="background: green;"></div>
+  {% for state, state_color in state_color_mapping.items() %}
+    <div class="legend_item" style="border: none;">{{state}}</div>
+    <div class="square" style="background: {{state_color}};"></div>
+  {% endfor %}
   {% for op in operators %}
   <div class="legend_circle" style="background:{{ op.ui_color }};">
   </div>
diff --git a/airflow/www_rbac/views.py b/airflow/www_rbac/views.py
index a626d87..326b635 100644
--- a/airflow/www_rbac/views.py
+++ b/airflow/www_rbac/views.py
@@ -63,7 +63,7 @@ from airflow.api.common.experimental.mark_tasks import (set_dag_run_state_to_suc
 from airflow.models import Connection, DagModel, DagRun, DagTag, Log, SlaMiss, TaskFail, XCom, errors
 from airflow.exceptions import AirflowException
 from airflow.models.dagcode import DagCode
-from airflow.settings import STORE_SERIALIZED_DAGS
+from airflow.settings import STATE_COLORS, STORE_SERIALIZED_DAGS
 from airflow.ti_deps.dep_context import RUNNING_DEPS, SCHEDULER_QUEUED_DEPS, DepContext
 from airflow.utils import timezone
 from airflow.utils.dates import infer_time_unit, scale_time_units
@@ -334,6 +334,7 @@ class Airflow(AirflowBaseView):
 
         state_color_mapping = State.state_color.copy()
         state_color_mapping["null"] = state_color_mapping.pop(None)
+        state_color_mapping.update(STATE_COLORS)
 
         return self.render_template(
             'airflow/dags.html',