diff --git a/airflow/www/templates/airflow/variable_list.html b/airflow/www/templates/airflow/variable_list.html index a9d58b2885d41..fe2b4182fca3b 100644 --- a/airflow/www/templates/airflow/variable_list.html +++ b/airflow/www/templates/airflow/variable_list.html @@ -38,4 +38,8 @@
{% endif %} {{ super() }} + {% endblock %} diff --git a/airflow/www/templates/airflow/variable_show.html b/airflow/www/templates/airflow/variable_show.html new file mode 100644 index 0000000000000..87fda206ceddb --- /dev/null +++ b/airflow/www/templates/airflow/variable_show.html @@ -0,0 +1,28 @@ +{# + 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 'appbuilder/general/model/show.html' %} + +{% block tail %} + {{ super() }} + +{% endblock %} diff --git a/airflow/www/templates/airflow/variable_show_widget.html b/airflow/www/templates/airflow/variable_show_widget.html new file mode 100644 index 0000000000000..e459bfa930311 --- /dev/null +++ b/airflow/www/templates/airflow/variable_show_widget.html @@ -0,0 +1,70 @@ +{# + 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. +#} + +{% import 'appbuilder/general/lib.html' as lib %} +{% include 'appbuilder/general/confirm.html' %} +{% include 'appbuilder/general/alert.html' %} + +{% block columns %} + +{% if fieldsets %} + + {% for fieldset_item in fieldsets %} + {% if fieldset_item[1].get('expanded') == None %} + {% set expanded = True %} + {% else %} + {% set expanded = fieldset_item[1].get('expanded') %} + {% endif %} + {% call lib.accordion_tag(loop.index,fieldset_item[0], expanded) %} +
+ + {% for item in fieldset_item[1].get('fields') %} + + + + + {% endfor %} +
{{label_columns.get(item)}}{{value_columns[include_columns.index(item)]}}
+ {% endcall %} + {% endfor %} + +{% else %} +
+ + + {% for item in include_columns %} + + + + + {% endfor %} +
{{label_columns.get(item)}} + {{value_columns[loop.index-1]}} +
+{% endif %} + +{% endblock columns %} + + +{% block actions %} +
+ {{ lib.render_action_links(actions, pk, modelview_name) }} + {{ lib.lnk_back() }} +
+{% endblock actions %} diff --git a/airflow/www/views.py b/airflow/www/views.py index 4179b72b115a4..37b7fce791d01 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -74,6 +74,7 @@ UserStatsChartView, ViewMenuModelView, ) +from flask_appbuilder.urltools import get_order_args, get_page_args, get_page_size_args from flask_appbuilder.widgets import FormWidget from flask_babel import lazy_gettext from jinja2.utils import htmlsafe_json_dumps, pformat # type: ignore @@ -129,7 +130,7 @@ DateTimeWithNumRunsWithDagRunsForm, TaskInstanceEditForm, ) -from airflow.www.widgets import AirflowModelListWidget +from airflow.www.widgets import AirflowModelListWidget, AirflowVariableShowWidget PAGE_SIZE = conf.getint('webserver', 'page_size') FILTER_TAGS_COOKIE = 'tags_filter' @@ -4068,6 +4069,9 @@ class VariableModelView(AirflowModelView): list_template = 'airflow/variable_list.html' edit_template = 'airflow/variable_edit.html' + show_template = 'airflow/variable_show.html' + + show_widget = AirflowVariableShowWidget datamodel = AirflowModelView.CustomSQLAInterface(models.Variable) # type: ignore @@ -4076,6 +4080,7 @@ class VariableModelView(AirflowModelView): 'add': 'create', 'list': 'read', 'edit': 'edit', + 'show': 'read', 'delete': 'delete', 'action_muldelete': 'delete', 'action_varexport': 'read', @@ -4091,6 +4096,7 @@ class VariableModelView(AirflowModelView): list_columns = ['key', 'val', 'description', 'is_encrypted'] add_columns = ['key', 'val', 'description'] edit_columns = ['key', 'val', 'description'] + show_columns = ['key', 'val', 'description'] search_columns = ['key', 'val'] base_order = ('key', 'asc') @@ -4116,6 +4122,26 @@ def prefill_form(self, form, request_id): if secrets_masker.should_hide_value_for_key(form.key.data): form.val.data = '*' * 8 + def prefill_show(self, item): + if secrets_masker.should_hide_value_for_key(item.key): + item.val = '*' * 8 + + def _show(self, pk): + pages = get_page_args() + page_sizes = get_page_size_args() + orders = get_order_args() + + item = self.datamodel.get(pk, self._base_filters) + if not item: + abort(404) + self.prefill_show(item) + widgets = self._get_show_widget(pk, item) + self.update_redirect() + + return self._get_related_views_widgets( + item, orders=orders, pages=pages, page_sizes=page_sizes, widgets=widgets + ) + extra_args = {"can_create_variable": _can_create_variable} @action('muldelete', 'Delete', 'Are you sure you want to delete selected records?', single=False) diff --git a/airflow/www/widgets.py b/airflow/www/widgets.py index c99c5d4d8332c..c62628382a843 100644 --- a/airflow/www/widgets.py +++ b/airflow/www/widgets.py @@ -72,3 +72,9 @@ class BS3TextAreaROWidget(BS3TextAreaFieldWidget): def __call__(self, field, **kwargs): kwargs['readonly'] = 'true' return super().__call__(field, **kwargs) + + +class AirflowVariableShowWidget(RenderTemplateWidget): + """Airflow variable show widget""" + + template = 'airflow/variable_show_widget.html'